Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flexbox - Search result popup underneath searchbox

Tags:

html

css

flexbox

I want to learn how to build a textbox that is an auto-expanding sort of search box like you see on Google:

Desired Result


Before

enter image description here

After

enter image description here

High-Level Design


In this design below, I demonstrate that I want it to visually seem as if the textbox itself is expanding. The way I see it, there is an input box for the text, but the height of the underlying searchbox-container is auto expanding on the y-axis.


enter image description here

Attempt


nav {
  font-family: "Inter", sans-serif;
  display: flex;
  border-bottom: 1px solid #b1aeae;
  background-color: #f7f7f7;
  height: 60px;
  width: 100%;
}

.nav-container {
  max-width: 925px;
  width: 80%;
  height: auto;
  margin: 0 auto;
}

.search-container {
  width: 50%;
  display: flex;
  align-items: center;
  flex-direction: column;
  position: relative;
}

.search-box {
  border: 1px solid #b7b5b5;
  height: 30px;
  width: 100%;
  background-color: white;
  border-radius: 50px;
  margin-top: 20px;
  display: flex;
  align-items: center;
}

.search-icon {
  padding-left: 15px;
}

.search-box input[type="text"] {
  border: none;
  margin-left: 20px;
  font-family: "Inter";
  width: 70%;
}

.search-box input[type="text"]:focus {
  outline-width: 0;
}

.search-results {
  display: flex;
  flex-direction: column;
  width: 98%;
  height: auto;
  border-radius: 0px;
  border-color: #b7b5b5;
  border-style: solid;
  background-color: white;
  border-width: 0px 1px 1px 1px;
  border-radius: 0px 0px 20px 20px;
  -webkit-box-shadow: 10px 13px 0px 0px rgba(0, 0, 0, 0.07);
  -moz-box-shadow: 10px 13px 0px 0px rgba(0, 0, 0, 0.07);
  box-shadow: 10px 13px 0px 0px rgba(0, 0, 0, 0.07);
}

.search-result:last-child {
  border-bottom: none;
}

.search-result:hover:last-child {
  border-bottom: none;
  border-radius: 0px 0px 20px 20px;
}

.search-result {
  width: 100%;
  border-bottom: 1px solid #b7b5b5;
  padding-left: 20px;
  padding-top: 10px;
  padding-bottom: 10px;
}

.search-result:hover {
  background-color: #f7f7f7;
}

.links-container {
  width: 55%;
  height: 100%;
}
    <nav>
      <div class="nav-container">
        <div class="search-container">
          <div class="search-box">
            <ion-icon name="search-outline" class="search-icon"></ion-icon>
            <input type="text" placeholder="Search articles & videos here" />
          </div>
          <div class="search-results">
            <div class="search-result">Result 1</div>
            <div class="search-result">Result 2</div>
            <div class="search-result">Result 3</div>
          </div>
        </div>
        <div class="links-container"></div>
      </div>
    </nav>

Current Outcome:

Clearly this is not looking good. I'm new to Flexbox so having some difficulty structuring this to achieve the previously mentioned goal.

enter image description here

like image 333
Ryan Avatar asked Nov 24 '25 10:11

Ryan


2 Answers

This had a lot of stuff that needed to change, so I pretty much rewrote it. Hopefully, I've given you some ideas to build on.

Some points:

  1. display: flex should only be set on a flex container, not on the cell elements.
  2. Use flex-basis if you need to set the width of a flex cell (don't use width).
  3. Don't use margins. Use flex-gap to space out your cells.
  4. Don't set the height unless you have to. Let the flex display try to set it for you first. In this example, we have to set the height of the link elements to keep them from being the same height as the search elements. (Short of using a grid, there's no way around that that I can see.)
  5. Prefer padding to size your elements. (Very much prefer it over height.)
  6. If you want something with two dimensions, don't use flex at all. Use grid. A vertical flex within a horizontal flex is beginning to push the envelope for what flex is intended for (a one-dimensional arrangement of a set of related elements); you could just as well set this up as a grid with blank areas beneath the menu.
  7. As for dynamically resizing the container div, you don't have to do anything special. If you programmatically add elements to the container, flex will take care of resizing it.

Here's some code:

    * {
      box-sizing: border-box;
    }

    nav {
      min-width: 800px;
      padding: 20px;
      background-color: #f7f7f7;
      width: 100%;
      justify-content: center;
      display: flex;
      column-gap: 40px;
    }

    a {
      text-decoration: none;
      padding: 20px;
    }

    .search-container {
      border: 2px solid darkgrey;
      border-radius: 20px;
      flex-basis: 40%;
      display: flex;
      flex-direction: column;
      justify-content: center;
      column-gap: 20px;
      z-index: 1;
    }

    .search-container a, .search-container p {
      border-bottom: 1px solid #b7b5b5;
      background-color: white;
      text-align: center;
    }

    .search-container p {
      margin: 0;
      padding: 30px 20px;
      border-top-left-radius: 20px;
      border-top-right-radius: 20px;
    }

    .search-container a:last-child {
      border: none;
      border-bottom-left-radius: 20px;
      border-bottom-right-radius: 20px;
    }

    .links-container {
      display: flex;
      padding: 10px 0;
      flex-basis: 40%;
      z-index: 1;
    }

    .links-container a {
      height: 60px;
      padding: 20px 40px;
      background-color: blue;
      color: white;
    }

    .links-container a:hover {
      background-color: green;
    }

    .header-overlay {
      width: 100%;
      min-width: 800px;
      height: 120px;
      background-color: lightgrey;
      position: absolute;
    }
<body>
  <header>
  <div class="header-overlay"></div>
    <nav>
      <div class="search-container">
        <p>Search Results</p>
        <a href="#">Result 1</a>
        <a href="#">Result 2</a>
        <a href="#">Result 3</a>
        <a href="#">Result 4</a>
        <a href="#">Result 5</a>
      </div>
      <div class="links-container">
        <a href="#">One</a>
        <a href="#">Two</a>
        <a href="#">Three</a>
      </div>
    </nav>
  </header>
</body>

As you can see, this code (especially the HTML) is simpler than yours. Basically, a flex is a container (with display: flex set) and a single set of nested elements. Any of those elements can be a container for another flex. That's what we have here: the nav is a flex with two elements, and each of those elements (search and links) is a flex container as well. A few observations:

  1. Using box-sizing: border-box everywhere will make your life a lot easier. You probably have had the experience of setting up two divs, setting their width to 50%, and being mystified that they won't fit on one line. It's because by default, padding and borders get added onto the outside of the div at the specified width, so its width becomes more than 50%. What this setting does is put padding and borders inside the width instead of outside it.
  2. Notice how to set border-radius for only some of the corners using border-top-left-radius, etc.
  3. Your design appears to want to have your search results drop below the header. This is a bit difficult to do with any setting for the search results themselves. The easier way to do it is to simply "fake" it overlaying a div at the top. You'll see that I've set div.header-overlay to position: absolute. That positions it at the top of the screen. Then, setting the z-index to 1 for both the search and links elements brings them above the header overlay.
  4. When you run the code here, the links take up more than 40% of the horizontal space; that's because the padding I used make it do that. I set the min-width to 800px so it wouldn't look too squashed, but that causes horizontal scrolling here, which isn't the best for an actual page. So, you'll want to play with flex-grow and flex-shrink, as well as media queries and different layouts for different screens, to make the layout more responsive.

That should give you some missing pieces for building flex displays. You can tinker with the markup and settings and learn more.

like image 58
BobRodes Avatar answered Nov 26 '25 23:11

BobRodes


Hope this works for you!

nav {
  display: flex;
  border-bottom: 1px solid #b1aeae;
  background-color: #f7f7f7;
  height: 60px;
  width: 100%;
}

.nav-container {
  display: flex;
  max-width: 925px;
  width: 80%;
  height: auto;
  margin: 0 auto;
}

.search-container {
  width: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  position: relative;
}

.search-box {
  border: 1px solid #b7b5b5;
  position: absolute;
  height: 30px;
  width: 100%;
  background-color: white;
  border-radius: 50px;
  padding-left: 20px;
  display: flex;
  flex-direction: column;
}

.search-results {
  width: 90%;
  display: flex;
  height: 200px;
  border-radius: 0px;
  border-color: #b7b5b5;
  border-style: solid;
  background-color: white;
  border-width: 0px 1px 1px 1px;
}

.search-result {
  width: 100%;
  border-bottom: 1px solid blue;
  height: 20px;
}

.links-container {
  width: 55%;
  height: 100%;
}

nav {
  display: flex;
  border-bottom: 1px solid #b1aeae;
  background-color: #f7f7f7;
  height: 60px;
  width: 100%;
}

.nav-container {
  display: flex;
  max-width: 925px;
  width: 80%;
  height: auto;
  margin: 0 auto;
}

.search-container {
  width: 50%;
  display: flex;
  justify-content: center;
  align-items: top;
  flex-direction: row;
  position: relative;
}

.search-box {
  border: 1px solid #b7b5b5;
  position: absolute;
  height: 30px;
  width: 100%;
  background-color: white;
  border-radius: 50px;
  padding-left: 20px;
  display: flex;
  flex-direction: column;
}

.search-results {
  width: 90%;
  display: flex;
  flex-direction:column;
  align-items: center;
  height: 200px;
  border-radius: 0px;
  border-color: #b7b5b5;
  border-style: solid;
  background-color: white;
  border-width: 0px 1px 1px 1px;
}

.search-result {
  position:relative;
  text-align:center;
  top: 40px;
  width: 100%;
  border-bottom: 1px solid blue;
  height: 20px;
  z-index: 9999;
}

.links-container {
  width: 55%;
  height: 100%;
}
<nav>
  <div class="nav-container">
    <div class="search-container">
      <div class="search-box"></div>
      <div class="search-results">
        <div class="search-result">Result 1</div>
        <div class="search-result">Result 2</div>
        <div class="search-result">Result 3</div>
        <div class="search-result">Result 4</div>
        <div class="search-result">Result 5</div>
      </div>
    </div>
    <div class="links-container"></div>
  </div>
</nav>
like image 34
Ravi Avatar answered Nov 26 '25 23:11

Ravi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!