XanderTEM
XanderTEM

Reputation: 109

Flexbox child shrinks beyond set minimum width

I'm having a serious CSS challenge on a small project I'm building:

I have a <main> element which is set as flexbox of row. inside are 3 children:

:root {
  --clr-light-text: #f2f2f2;
  --clr-dark-text: #48484a;
  --shadow-default: 0px 2px 8px rgba(0, 0, 0, 0.2);
  --vid-container-h: 0px;
  color: var(--clr-light-text);
  font-family: 'Poppins', sans-serif;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  list-style: none;
  text-decoration: none;
}

h1,
h2,
h3,
h4 {
  font-weight: 400;
}

body {
  background-color: var(--clr-dark-text);
  text-align: center;
  overflow-x: hidden;
  scroll-behavior: smooth;
}

.glass {
  background-image: linear-gradient( 135deg, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0));
  backdrop-filter: blur(5px);
  border: 1px solid rgba(255, 255, 255, 0.15);
  box-shadow: var(--shadow-default);
  border-radius: 0.5rem;
}

main {
  display: flex;
  justify-content: center;
  padding: 0 1rem;
  gap: 2rem;
}

.main-container {
  background-color: hsl(0, 0%, 75%);
  padding-bottom: 10rem;
  position: relative;
}

.weather-box {
  width: clamp(13.5rem, 18%, 20rem);
  display: flex;
  flex-direction: column;
  justify-content: space-evenly;
  padding: 0 1em 1em 1em;
}

#weather-icon {
  margin: -15% -10%;
}

.weather-details {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

#forecast,
#temp,
#humidity {
  display: flex;
  flex-direction: column;
  align-items: center;
}

#temp {
  margin-bottom: 1em;
  font-weight: 200;
}

#temp-num {
  font-size: 3em;
}

#humid {
  font-size: 1.5em;
}

#humid-value {
  font-size: 1.5em;
  font-weight: 200;
}

#humid-value img {
  max-width: 1em;
}

#forecast-desc {
  font-size: 2.5em;
  font-weight: 400;
}

.playlist-box {
  width: clamp(13.5rem, 18%, 20rem);
  display: flex;
  align-items: center;
  flex-direction: column;
  padding: 1rem 0.5em;
  flex-shrink: 0;
}

.playlist-box h3::after {
  content: '';
  width: 70%;
  height: 1px;
  background-color: rgba(255, 255, 255, 0.3);
  border-radius: 100vmax;
  display: block;
  margin: 1em auto;
}

#playlist {
  display: grid;
  width: 100%;
  padding: 1em;
  overflow-y: scroll;
  scroll-behavior: smooth;
}

#playlist li {
  margin-bottom: 1rem;
  width: 100%;
  padding: 1rem;
  border: 1px solid rgba(255, 255, 255, 0);
}

#playlist li:hover,
#playlist li:focus {
  background-image: linear-gradient( 135deg, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0));
  border: 1px solid rgba(255, 255, 255, 0.15);
  box-shadow: var(--shadow-default);
  border-radius: 0.5rem;
}

.song-title {
  margin-bottom: 0.5em;
}

.vid-thumb {
  width: 100%;
  /* object-position: center;
  object-fit: cover; */
}

.video-container {
  align-self: flex-start;
  padding: 1em;
}

#song-frame {
  position: relative;
  overflow: hidden;
  width: 100%;
  padding-top: 56.25%;
}

#song-frame iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
<div class="main-container">
  <main>
    <aside class="weather-box glass">
      <div id="forecast">
        <img id="weather-icon" src="http://openweathermap.org/img/wn/[email protected]" alt="Weather Icon" />
        <span id="forecast-desc">(--)</span>
      </div>
      <div class="weather-details">
        <div id="temp">
          <span id="temp-num">0&deg;c</span>
          <span id="feels-like">feels like 0&deg;c</span>
        </div>
        <div id="humidity">
          <span id="humid">Humidity</span>
          <div id="humid-value">
            <span id="humid-num">0%</span>
          </div>
        </div>
      </div>
    </aside>

    <div class="video-container glass">
      <div id="song-frame">
        <iframe src="https://www.youtube.com/embed/oG08ukJPtR8" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" width="1024" height="576" frameborder="0"></iframe>
      </div>
    </div>
    <aside class="playlist-box glass">
      <h3>Browse Playlist:</h3>
      <ul id="playlist">
        <li>
          <h4>Song Title</h4>
          <img class="vid-thumb" src="https://i.ytimg.com/vi/ru0K8uYEZWw/hqdefault.jpg" alt="" />
        </li>
        <li>
          <h4>Song Title</h4>
          <img class="vid-thumb" src="https://i.ytimg.com/vi/pkCyfBibIbI/hqdefault.jpg" alt="" />
        </li>
      </ul>
    </aside>
  </main>
</div>

I applied to both <aside> elements to have a responsive width with the following width: clamp(13.5rem, 18%, 20rem). The div in the center uses the rest of the available width of the viewport. Generally, the layout kinda works.

The weather-container's clamp works just fine. The playlist-container though is able to shrink to less than 13.5rem (216px) and in some screen sizes I'm left with uneven containers in the sides.

The interesting part is that problem is somehow connected to the <img> thumbnails. The set width for them is 100%. If I cancel it out, the container behaves correctly but the thumbnails are cut off.

Would love to get over this problem, thank you.

Edit: I've produced a CodePen which recreates the problem: https://codepen.io/xandertem/pen/XWZLaVR

Try going to responsive mode and see the right section shrinking around <560px.

Upvotes: 2

Views: 1246

Answers (2)

Michael Benjamin
Michael Benjamin

Reputation: 371003

Adding flex-shrink: 0 to the aside (.playlist-box) solves the problem.

You should probably add the same rule to the other aside (.weather-box), even though you don't need it, just in case the type of content in that container ever changes. As you can see, images and videos make a difference.

Upvotes: 3

A Haworth
A Haworth

Reputation: 36426

For reasons I don't understand clamp in the width setting of flex just does not seem to work.

Also to automatically have the two asides with the height of the middle item you could use grid.

To get round what seems to be the clamp problem this snippet separates out the ranges by using min and max width media queries [when 18% is 13.5rem the overall width is 75rem and so on).

* {
  box-sizing: border-box;
}

main {
  display: grid;
  grid-template-columns: 18% 1fr 18%;
  width: 100vw;
}

@media screen and (max-width: 75rem) {
  main {
    grid-template-columns: 13.5rem 1fr 13.5rem;
  }
}

@media screen and (min-width: 111.111rem) {
  main {
    grid-template-columns: 20rem 1fr 20rem;
  }
}

main {
  padding: 0 1rem;
  gap: 2rem;
}

.weather-container {
  display: flex;
  flex-direction: column;
  justify-content: space-evenly;
  padding: 0 1em 1em 1em;
}

.video-container {
  padding: 1em;
}

.playlist-container {
  display: flex;
  align-items: center;
  flex-direction: column;
  padding: 1rem 0.5em;
}

.vid-thumb {
  width: 100%;
  /* object-position: center;
  object-fit: cover; */
}
<main>
  <div class="weather-container">
    ...divs...
  </div>
  <div class="video-container">
    <div>
      <iframe>...</iframe>
    </div>
  </div>
  <div class="playlist-container">
    <h3>Browse Playlist:</h3>
    <ul>
      <li>
        <h4>Song Title</h4>
        <img class="vid-thumb" src="https://i.ytimg.com/vi/example.jpg" alt="">
      </li>
      <li>etc...</li>
    </ul>
  </div>
</main>

Upvotes: 1

Related Questions