0

I am trying to build a website which I also use angular. I need to perfectly centre a div element which contains some icons (around 80) and those icons must be left aligned. Contents are filtered via text input and this filtration results in different numbers of icons every time. I've tried a grid system similar to a bootstrap's grid, flexbox, whatever. Either a small extra area is left blank on the right side when I align my contents to left, or all the elements are centred and the bottom elements are centred and the div does not look organized. Moreover, I need to keep at least 10 px of margins between each icon. Can anyone help me?

.notfound {
  text-align: center;
}

.iconelement:hover {
  background-color: #ffffff;
  box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.16);
  color: #000000;
}

.iconelement:active {
  background-color: #2974d4;
  box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.16);
  color: #ffffff;
}

.grid-container {
  background-color: #fdfdfd;
  padding-bottom: 20px;
  display: flex;
  justify-content: center;
  text-align: left;
  flex-wrap: wrap;
}

.iconelement {
  width: 60px;
  height: 60px;
  border-radius: 4px;
  background-color: #fdfdfd;
  text-align: center;
  margin: 10px;
  float: none;
  color: #000000;
}

.icons {
  position: relative;
  top: 50%;
  transform: translateY(-50%);
  font-size: 2em;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="ui-g ">
  <div class="ui-g-12" *ngIf="(icons|filter:searchText).length===0">
    <div class=" ui-g-12 notfound">
      <h3>No results for "{{searchText}}"</h3>
    </div>
  </div>
</div>
<div class="ui-xl-3 ui-lg-3 ui-md-2 ui-sm-1" (click)="unselectIcon()"></div>
<div class=" ui-xl-6 ui-lg-6 ui-md-8 ui-sm-10 ">
  <div class="ui-g-12  grid-container">
    <div class="ui-g-1 iconelement" *ngFor="let icon of icons| filter : searchText; let i = index " (click)="getIcon(icon.id)">
      <i class="icons {{icon.name}}"></i>
    </div>
  </div>
</div>
<div class="ui-xl-3 ui-lg-3 ui-md-2 ui-sm-1" (click)="unselectIcon()"></div>
</div>

ps: text align: center does not solve this problem.

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • Probably duplicate - https://stackoverflow.com/questions/32802202/how-to-center-a-flex-container-but-left-align-flex-items – Paulie_D Aug 07 '18 at 11:32
  • Also related - https://stackoverflow.com/questions/34995740/css-when-inline-block-elements-line-break-parent-wrapper-does-not-fit-new-width – Paulie_D Aug 07 '18 at 11:32
  • This is not a duplicate of the problem which you sent in the first link. centring div elements does not work like list elements. Moreover, I've tried the solution before and this does not fix it. justifying content left leads to the first problem that I have. – Ege Darçın Aug 07 '18 at 11:46
  • 2
    Unfortunately, you haven't provided code that **demonstrates** the issue so were' working from a "word picture" which is somewhat unclear...hence the *"possible"* duplicate. Perhaps if you can make an actual **minimal demo** we can we what you're working with. – Paulie_D Aug 07 '18 at 12:03

2 Answers2

1

If your goal is to create a responsive auto-centering container where items (icons) maintain the same width while the gaps between items adapt, your best way to do that currently is probably flexbox (and grids in the future). An example here.

The issue with flexbox based layouts, though, is how to have the last row aligned to the left. You could try some of the solutions proposed in this thread, however they work only in certain situations. Oftentimes you would need to use javascript to achieve this. I created a function for that and could post it somewhere should you be interested.

Generally, when you're dealing with this kind of a problem, you should consider, which elements need to adapt. Whether the gap between elements, the elements themselves or the container where elements reside.


Flexible gap - fixed elements - fixed/flexible container

Manageable by the approach I described above - flexbox to stretch the gap, fixed width on the elements and possibly javascript to align last row.

Fixed gap - flexible elements - fixed/flexible container

Fixed padding and flex attribute on the element.

Fixed gap - fixed elements - fixed container

Use float: left on the elements and put all into a container of defined dimensions. The container's width must be in multiples of elements width + padding to be centered, affected by how many elements should be on each line.

Fixed gap - fixed elements - flexible container

This is fairly well doable with flex attribute again. Often though there is a need to set a minimal width and we're back at case #1.

So achieving a fully responsive centered element with left-aligned items is currently a challenge. If you need perfection at all costs, I'd suggest using several media queries instead to make sure it always looks the way you want (As discussed here for example).

Dan
  • 473
  • 3
  • 13
0

I have found my solution but it was not in the way I've wanted. I've got rid of all the ui-g grid layout except the grid itself. (the main reason that I've been using it is to run my page on all browsers, ie11 cause many problems with new technologies) I also used flex (flex-wrap as recommended) to keep the elements in the div. That way the icons covered 100% of the screen in width. To contain the items I have a maximum width but this meant that the responsiveness of the container is not there anymore. that is why I don't like this solution. To patch this, I used @media screen to adjust the number of elements displayed depending on the screen size. To make it perfect it needed many trials and errors but a fix is a fix. Fixing all the elements is done by "margin: auto;" here is the code after fix:

<div class="ui-g">
<div class="notfound" *ngIf="(icons|filter:searchText).length===0">
    <h3>No results for "{{searchText}}"</h3>
</div>
  <div class="ui-g-12 grid-container">
    <div class="ui-g-1 iconelement" *ngFor="let icon of icons| filter : searchText; let i = index "(click)="getIcon(icon.id)">
      <i class="icons pi pi-{{icon.name}}" ></i>
    </div>
  </div>

In the div at the top I still use class=ui-g" to push down the sticky element which displays the icon details. Each icon has the width and height of 60 px and has 10 px margin, so I needed to calculate the sum of the width and apply it according to the screen and how many icons I need to see side by side.

CSS:

.notfound {
  text-align: center;
  margin: auto;
  width: 100%;
}

.iconelement:hover {
  background-color: #ffffff;
  box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.16);
  color: #000000;
}

.iconelement:active {
  background-color: #2974d4;
  box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.16);
  color: #ffffff;
}

.grid-container {
  background-color: #fdfdfd;
  padding-bottom: 20px;
  display:flex;
  flex-wrap: wrap;
  max-width: 660px;
  margin: auto;
}
.iconelement {
  width: 60px;
  height: 60px;
  border-radius: 4px;
  background-color: #fdfdfd;
  text-align: center;
  margin: 10px;
  float: none;
  color: #000000;
}

.icons {
  position: relative;
  top: 50%;
  transform: translateY(-50%);
  font-size: 2em;
}

@media screen and (max-width: 430px) {
  .grid-container{
    max-width: 260px;
  }
}

the last bit is for the width configuration.