0

Hi everyone, i'm currently working on a note project, i'm trying to center my notes using flex box without any useless spaces, take a look at the photos you will understand what i mean .

enter image description here

bottom space is just fine, the problem is the space that is caused by flex box on the right side , i want the yellow box to resize and fit but stay centered as well, the yellow box is a ul tag and the red boxes are li tags.

here is the css styles : ( container includes the whole page except the header )

.container {
  width: 100%;
  display: flex;
  height: 100vh;
  align-items: flex-start;
  justify-content: center;
  position: relative;
}

ul {
  align-content: flex-start;
  margin: 40px auto;
  max-width: 1400px;
  width: fit-content;
  height: 80vh;
  display: flex;
  justify-content: flex-start;
  align-items: flex-start;
  flex-wrap: wrap;
  overflow-y: scroll;
  margin-top: 100px;
  border: 3px solid yellow;
}

ul li {
  border: 2px solid red;
  list-style-type: none;
  font-size: 20px;
  margin: 5px;
  background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5));
  backdrop-filter: blur(10px);
  width: 330px;
  height: 200px;
  display: flex;
  overflow: hidden;
  justify-content: space-between;
  align-items: flex-start;
  flex-direction: column;
  padding: 20px;
  border-radius: 5px;
  position: relative;
  transition: height 0.3s;
}

here is the HTML codes : ( sorry it's not clean )

<title>Dashboard</title>

<div class="container">
  <ul>
    <li class="item">
      <div class="priority"></div><span class="title c-title"> title </span>
      <span class="content c-content"> Content </span>
      <span class="date"> date </span>

      <div class="item_buttons">
        <a href=""><button class="detail faint_color"><img class="edit-icon" src="/icons/invisible.svg" alt="see icon"></button></button></a>
        <a href=""><button class="detail faint_color"><img class="edit-icon" src="/icons/edit.svg" alt="edit icon"></button></button></a>
        <a href=""><button class="deleteButton detail faint_color"><img class="edit-icon" src="/icons/trash.svg" alt="delete icon"></button></a>
      </div>
    </li>
  </ul>
</div>

<div class="addButton">
  <img class="addButtonImage" src="/add.svg" alt="add new note" />
  <div class="smallMenu hide">
    <a href="/modify/folders">
      <button class="folders_button"><img src="/icons/folder.svg" alt="folder icon"></button>
    </a>
    <a href="/note/add">
      <button class="addNote_button"><img src="/icons/pen.svg" alt="pen icon"></button>
    </a>
  </div>
  </div>
Ritalin
  • 15
  • 4
  • Could you please include the HTML code as well? – SnoopFrog Jan 24 '23 at 15:05
  • yes sure, thanks for your time, i placed html codes but header is not included because header has it's own styles, didn't want to make it hard to read, let me know if you need anything – Ritalin Jan 24 '23 at 15:17
  • @Ritalin I see now and I don't think you can do what you're trying to do with pure CSS/HTML, because HTML/CSS doesn't know when elements wrap so the parent can't have dynamic size based on how many elements can fit currently. You would need to calculate it with JS. – SnoopFrog Jan 24 '23 at 15:22
  • 1
    Does this answer your question? [How to center a flex container but left-align flex items](https://stackoverflow.com/questions/32802202/how-to-center-a-flex-container-but-left-align-flex-items) – Daniel Cheung Jan 24 '23 at 15:24

3 Answers3

1

As I said in the comment, I don't think you can solve this using pure HTML/CSS, but you could calculate how many elements can fit at given time inside your .container and change width of your ul.

Check this code below:

function totalWidth(element) {
  style = window.getComputedStyle(element)
  return parseFloat(style.marginLeft) + parseFloat(style.marginLeft) + parseFloat(style.width)
}

function resizeContainer() {
  const container = document.querySelector(".container")
  const element = document.querySelector(".container ul")
  const children = document.querySelector(".container ul li")
  const childrenWidth = totalWidth(children)
  const amountFits = Math.floor(Math.min(container.offsetWidth, 1400) / childrenWidth)
  element.style.width = `${childrenWidth * amountFits}px`
}

resizeContainer()
window.addEventListener("resize", resizeContainer)
.container {
  width: 100%;
  display: flex;
  height: 100vh;
  align-items: flex-start;
  justify-content: center;
  position: relative;
}

ul {
  align-content: flex-start;
  margin: 40px auto;
  max-width: 1400px;
  width: fit-content;
  height: 80vh;
  display: flex;
  justify-content: flex-start;
  align-items: flex-start;
  flex-wrap: wrap;
  overflow-y: scroll;
  margin-top: 100px;
  border: 3px solid yellow;
  padding: 0;
}

ul li {
  border: 2px solid red;
  list-style-type: none;
  font-size: 20px;
  margin: 5px;
  background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5));
  backdrop-filter: blur(10px);
  width: 330px;
  height: 200px;
  display: flex;
  overflow: hidden;
  justify-content: space-between;
  align-items: flex-start;
  flex-direction: column;
  padding: 20px;
  border-radius: 5px;
  position: relative;
  transition: height 0.3s;
  box-sizing: border-box;
}
<div class="container">
<ul>
<li>test</li><li>test</li>
<li>test</li><li>test</li>
</ul>
</div>

Mind the fact that I added box-sizing: border-box; to your ul li so it's a bit easier to calculate the actual size of the element. Naturally you could ignore this and change my totalWidth method to calculate it the way you'd like.

I don't think you can do it differently but I'd like to be proven wrong.

SnoopFrog
  • 684
  • 1
  • 10
1

There's a number of solutions for this one, depending which way you want to go,

If the notes don't have to be exactly 330px wide, you can achieve removing the gaps by replacing:

width: 330px;

with

flex: 200px;

This takes advantage of the fluid responsiveness of flexbox.

One issue with this flex solution is the 'leftover' element upon wrapping: e.g. with three elements across, the fourth will wrap and grow to the full width of the parent:

CSS flex-grow causing the last element to stretch out

To get around this with flex, you would need to either:

  1. change flex to something like flex: 0 1 50%; with percentage values and flex-grow disabled, which means you would need @media queries to give the lists the fluidity they had before
  2. use a JavaScript solution to dynamically set the width of the last element based on the other lists (like @SnoopFrog's answer)

If you do need the notes to be 330px wide, I would set the parent <ul> to have a set size twice that of the lists width: 785px; and ensure that justify-content: center;


Alternatively, turning to CSS grid or a simple inline-block method may fit your needs but both would need @media queries for responsivity.

Airofoil
  • 36
  • 1
0

* {
    /* just for reset and for remove all margins and paddings */
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

ul {
    display: flex;
    /*justify-content: flex-start; don't need this, is start by default
    align-items: flex-start;*/
    /* magical words that they can align internal box(li) */
    justify-content: center;  
    align-items: center;

    margin: 40px auto; /*auto <--> both part is ok*/
    max-width: 1400px;
    /* just for see the center(you can remove this width static of 25rem */
    width: 25rem; /* width: fit-content; */
    height: 80vh;
    overflow-y: scroll;
    margin-top: 100px;
    border: 3px solid yellow;
}

ul li {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    flex-direction: column;

    border: 2px solid red;
    list-style-type: none;
    background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5));
    backdrop-filter: blur(10px);
    width: min(100%, 330px);   /*make it responsive, when shrink down, under 330px, is take 100% of width avaiable, and not overflowing*/
    height: 200px;
    margin: 10px auto; /*in every elements, you can use margin auto for both parts*/
    padding: 20px;
    border-radius: 5px;
    transition: all 0.3s; /*transition:height 0.3  --> not height, but all inside!*/
    /* overflow: hidden; don't need, that not should be overflow */
    /* position: relative; Is by default! like height:auto*/
}

/* if you want to style your buttons, write this code all times */
/* remove deafult aspect of a btn and others, beacuse every browser take a different style*/
button, input, a {
    appearance: none;
        -webkit-appearance: none;
            -moz-appearance: none;
}
<title>Dashboard</title>


    <ul>
        <div class="wrapper">
            <li class="item">
                <div class="priority"></div>
                <span class="title c-title"> title </span>
                <span class="content c-content"> Content </span>
                <span class="date"> date </span>

                <div class="item_buttons">
                    <a href="">
                        <button class="detail faint_color">
                            <img class="edit-icon" src="/icons/invisible.svg" alt="see icon">
                        </button>
                    </a>
                    <a href="">
                        <button class="detail faint_color">
                            <img class="edit-icon" src="/icons/edit.svg" alt="edit icon">
                        </button>
                    </a>
                    <a href="">
                        <button class="deleteButton detail faint_color">
                            <img class="edit-icon" src="/icons/trash.svg" alt="delete icon">
                        </button>
                    </a>
                </div>
            </li>
        </div>
    </ul>


    <div class="addButton">
        <img class="addButtonImage" src="/add.svg" alt="add new note" />
        <div class="smallMenu hide">
            <a href="/modify/folders">
                <button class="folders_button">
                    <img src="/icons/folder.svg" alt="folder icon">
                </button>
            </a>
            <a href="/note/add">
                <button class="addNote_button">
                    <img src="/icons/pen.svg" alt="pen icon">
                </button>
            </a>
        </div>
    </div>