Home > other >  Creating a perfect circle around a text while using flex & flex-basis to position elements
Creating a perfect circle around a text while using flex & flex-basis to position elements

Time:11-04

I have this HTML page and I'm trying to position 8 perfect circles on two rows. (4 on each)

I achieved that using flexbox, but then my circle will be broken. I expect this to happen because I don't have a fixed width and height - but the problem is, the circle's dimensions cannot be fixed, because they are set by flex-basis.

Here's the code:

.content-achievements {
  width: 100%;
  height: 30rem;
  position: relative;
  border: 1px solid black;
  border-radius: 25px;
  margin-left: 1.5rem;
  text-align: center;
}

.achievements-title {
  border: 1px solid black;
  border-radius: 1.5rem;
  width: 95%;
  margin: 1.5rem auto;
  height: 2.5rem;
  line-height: 2.5rem;
}

.achievements-list {
    border: 1px solid black;
    width: 95%;
    text-align: center;
    margin: 0 auto;
    border-radius: 1.5rem;
    margin-bottom: 1rem;
}

.achievements-items {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-content: center;
    gap: 20px;
    margin: 1rem 0;
}

.achievements-item {
    display: inline-block;
    flex-basis: 20%;
    border-radius: 50%;
    border: 1px solid #000;
    line-height: 2rem;
}
<div class="content-achievements">
            <div class="achievements-title">
                Game Achievements
            </div>
            <div class="achievements-list">
                <ul class="achievements-items">
                    <li class="achievements-item">achiev1</li>
                    <li class="achievements-item">achiev2</li>
                    <li class="achievements-item">achiev3</li>
                    <li class="achievements-item">achiev4</li>
                    <li class="achievements-item">achiev5</li>
                    <li class="achievements-item">achiev6</li>
                    <li class="achievements-item">achiev7</li>
                    <li class="achievements-item">achiev8</li>
                </ul>
            </div>

        </div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

How can I fix my circles while also keeping this layout?

Thanks.

CodePudding user response:

It can be done using CSS property aspect-ratio for the circle items:

.achievements-items {
  aspect-ratio: 1;
}

And adapt main container's height to its new dynamic content height accordingly:

.content-achievements {
  ...
  height: auto;
  ...
}

CodePudding user response:

set a static size that is the same for height and width for all circles elements:

.achievements-items {
  width: 40px;
  height: 40px;
}

CodePudding user response:

try to use flexbox inside of it use grid for better specify your rows and columns it work with that:

.achievements-list{
    display:flex; 
    justify-content:center;
    justify-items:center;
    border:1px solid black;
    width:95%;
    text-align:center;
    margin:0 auto;
    border-radius:1.5rem;
    margin-bottom:1rem;
}
.achievements-items{
    display: grid;
    grid-template-columns: auto auto auto auto;
    gap: 50px;
    margin: 1rem 0;
}

.achievements-item{
    list-style-type: none;
    width: 60px;
    height: 60px;
    border-radius: 50%;
    border: 1px solid #000;
    line-height: 2rem;
}

CodePudding user response:

Back when there was no aspect-ratio and even now, since it is not yet wildly supported, a common method would be to make three elements instead of one and use a padding-bottom trick. You see, when you set padding in percentage, it is calculated in relative to the width of the containing block. It is true for vertical padding (top/bottom) as it is for horizontal (right/left). This means if you set padding-bottom: 100% this "100%" will equals the parent container width, not height. So we can do this:

  • outer element — defines width
  • middle element — defines height via padding-bottom, also has position: relative
  • inner element — holds the content, also has position: absolute

Below I have added two span tags for each li and applied this trick.

* {
  margin: 0;
  box-sizing: border-box;
}
.content-achievements {
  width: 100%;
  height: 30rem;
  position: relative;
  border: 1px solid black;
  border-radius: 25px;
  text-align: center;
}

.achievements-title {
  border: 1px solid black;
  border-radius: 1.5rem;
  width: 95%;
  margin: 1.5rem auto;
  height: 2.5rem;
  line-height: 2.5rem;
}

.achievements-list {
  border: 1px solid black;
  width: 95%;
  text-align: center;
  margin: 0 auto;
  border-radius: 1.5rem;
  margin-bottom: 1rem;
}

.achievements-items {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-content: center;
  gap: 20px;
  margin: 1rem 0;
}

.achievements-item {
  display: inline-block;
  flex-basis: 20%;
  line-height: 2rem;
  position: relative;
}

.achievements-item>span {
  position: relative;
  display: block;
  padding-bottom: 100%;
  border-radius: 50%;
  border: 1px solid #000;
}

.achievements-item>span>span {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}
<div class="content-achievements">
  <div class="achievements-title">
    Game Achievements
  </div>
  <div class="achievements-list">
    <ul class="achievements-items">
      <li class="achievements-item"><span><span>achiev1</span></span></li>
      <li class="achievements-item"><span><span>achiev2</span></span></li>
      <li class="achievements-item"><span><span>achiev3</span></span></li>
      <li class="achievements-item"><span><span>achiev4</span></span></li>
      <li class="achievements-item"><span><span>achiev5</span></span></li>
      <li class="achievements-item"><span><span>achiev6</span></span></li>
      <li class="achievements-item"><span><span>achiev7</span></span></li>
      <li class="achievements-item"><span><span>achiev8</span></span></li>
    </ul>
  </div>
</div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related