Flexbox — всплывающее окно результатов поиска под searchbox

#html #css #flexbox

#HTML #css #flexbox

Вопрос:

Я хочу узнать, как создать текстовое поле, которое представляет собой автоматически расширяющееся окно поиска, подобное тому, которое вы видите в Google:

Желаемый результат


Перед

введите описание изображения здесь

После

введите описание изображения здесь

Дизайн высокого уровня


В этом дизайне ниже я демонстрирую, что я хочу, чтобы визуально казалось, что само текстовое поле расширяется. На мой взгляд, для текста есть поле ввода, но высота базового контейнера searchbox автоматически увеличивается по оси y.


введите описание изображения здесь

Попытка


 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 amp; 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>  

Текущий результат:

Очевидно, что это выглядит не очень хорошо. Я новичок в Flexbox, поэтому у меня возникли некоторые трудности с структурированием этого для достижения ранее упомянутой цели.

введите описание изображения здесь

Комментарии:

1. Возможно, вы захотите взглянуть на функцию фрагмента кода в stackoverflow. Отредактируйте свой пост и нажмите Ctrl-M, и вы должны точно увидеть, что нужно делать. Это создаст фрагмент, который каждый может запустить и посмотреть, как выглядит результат. Проще для всех! 🙂

2. @BobRodes Круто, добавил, спасибо!

3. удалить display: block из search-results класса

4. @Hyetigran Я обновил доступный для выполнения фрагмент выше, я вижу в основном проблему с полями, но добавление чего-то вроде margin-top не является решением для меня, поскольку оно искажается при изменении числа результатов.

5. Возможно, вам потребуется добавить JS для динамического отображения результатов поиска. Поле поиска должно содержать входные данные. Наконец, вы могли бы использовать JS для захвата координат X и Y окна поиска и отображения результатов поиска под ним.

Ответ №1:

В нем было много вещей, которые нужно было изменить, поэтому я в значительной степени переписал его. Надеюсь, я дал вам несколько идей для развития.

Некоторые моменты:

  1. display: flex должно быть установлено только для контейнера flex, а не для элементов cell.
  2. Используйте, flex-basis если вам нужно установить ширину гибкой ячейки (не используйте width ).
  3. Не используйте поля. Используйте flex-gap для выделения ячеек.
  4. Не устанавливайте высоту, если в этом нет необходимости. Пусть гибкий дисплей сначала попытается настроить его для вас. В этом примере мы должны установить высоту элементов ссылки, чтобы они не были такой же высоты, как элементы поиска. (Если не использовать сетку, я не вижу способа обойти это.)
  5. Предпочитайте заполнение для определения размера ваших элементов. (Очень предпочитаю это height .)
  6. Если вам нужно что-то с двумя измерениями, вообще не используйте flex. Используйте сетку. Вертикальный flex внутри горизонтального flex начинает расширять границы того, для чего предназначен flex (одномерное расположение набора связанных элементов); вы могли бы также настроить это как сетку с пустыми областями под меню.
  7. Что касается динамического изменения размера контейнера div, вам не нужно делать ничего особенного. Если вы программно добавляете элементы в контейнер, flex позаботится о его изменении.

Вот некоторый код:

     * {
      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>  

Как вы можете видеть, этот код (особенно HTML) проще вашего. По сути, flex — это контейнер (с display: flex набором) и одним набором вложенных элементов. Любой из этих элементов может быть контейнером для другого flex. Вот что мы имеем здесь: nav это гибкий файл с двумя элементами, и каждый из этих элементов (поиск и ссылки) также является гибким контейнером. Несколько наблюдений:

  1. Использование box-sizing: border-box везде сделает вашу жизнь намного проще. Вероятно, у вас был опыт настройки двух div файлов, установки их ширины на 50% и озадачивания тем, что они не помещаются в одну строку. Это потому, что по умолчанию отступы и границы добавляются к внешней части div с указанной шириной, поэтому его ширина становится больше 50%. Что делает этот параметр, так это помещает отступы и границы внутри ширины, а не за ее пределы.
  2. Обратите внимание, как установить border-radius только для некоторых углов, используя border-top-left-radius и т.д.
  3. Похоже, что ваш дизайн хочет, чтобы результаты поиска отображались ниже заголовка. Это немного сложно сделать с любыми настройками для самих результатов поиска. Самый простой способ сделать это — просто «подделать» его, наложив div вверху. Вы увидите, что я установил div.header-overlay значение position: absolute . Это помещает его в верхней части экрана. Затем, установив z-index значение 1 как для элементов search, так и для links, они окажутся над наложением заголовка.
  4. Когда вы запускаете приведенный здесь код, ссылки занимают более 40% горизонтального пространства; это потому, что отступ, который я использовал, позволяет это делать. Я установил min-width значение 800 пикселей, чтобы оно не выглядело слишком сжатым, но это приводит к горизонтальной прокрутке, что не самое лучшее для реальной страницы. Итак, вам захочется поиграть с flex-grow и flex-shrink , а также с медиа-запросами и разными макетами для разных экранов, чтобы сделать макет более отзывчивым.

Это должно дать вам некоторые недостающие элементы для создания гибких дисплеев. Вы можете повозиться с разметкой и настройками и узнать больше.

Комментарии:

1. Эй, @Bob, я действительно ценю эту статью. Я перечитал это несколько раз сегодня утром и определенно кое-что узнал. Большое спасибо!

2. Мой единственный вопрос, который у меня есть здесь. Как я могу увеличить результаты поиска, не влияя на высоту того, что находится под ним? Другими словами, без нажатия на все элементы, которые существуют под заголовком.

3. @Райан Да, это действительно нужно решить. Возможно, вы можете реализовать приведенные предложения, а затем задать это как другой вопрос. Для всех будет проще, если мы будем рассматривать это как отдельную проблему.

Ответ №2:

Надеюсь, это сработает для вас!

 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>  

Комментарии:

1. Спасибо @Ravindra. Может ли текстовое поле быть выровнено по центру на навигаторе?

2. Я обновил свой фрагмент, и он ближе к тому, что я хочу, но не уверен, делаю ли я что-то слишком странное.

Ответ №3:

Добавьте это для выравнивания по центру div

 .search-container {
  align-items: top;
  flex-direction: row;
}
  

вместо

 .search-container {
  align-items: center;
  flex-direction: column;
}
  

И добавить
.search-results {align-items: center;} для выравнивания по центру

затем добавьте в search-result ,

 .search-result {
  position:relative;
  text-align:center;
  top: 40px;
  z-index: 9999;
}
  

Для результата поиска добавьте js

 function myFunction() {
    var input, filter, ul, li, a, i, txtValue;
    input = document.getElementById("search-box");
    filter = input.value.toUpperCase();
    ul = document.getElementById("search-results");
    li = ul.getElementsByTagName("div");
    for (i = 0; i < li.length; i  ) {
        a = li[i];
        txtValue = a.textContent || a.innerText;
        if (txtValue.toUpperCase().indexOf(filter) > -1) {
            li[i].style.display = "";
        } else {
            li[i].style.display = "none";
        }
    }
}
  

Рабочая демонстрация

 function searching(input) {
    input.classList.add("active");
    var input, filter, ul, li, a, i, txtValue;
    filter = input.value.toUpperCase();
    ul = document.getElementById("search-results");
    li = ul.getElementsByTagName("div");
    for (i = 0; i < li.length; i  ) {
        a = li[i];
        txtValue = a.textContent || a.innerText;
        if (txtValue.toUpperCase().indexOf(filter) > -1) {
            li[i].style.display = "";
        } else {
            li[i].style.display = "none";
        }
    }
}

function fun(obj){
   obj.classList.add("active");
}  
 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:0 30px;
  display: flex;
  top:18px;
  flex-direction: column;
}
.search-box.active{
  border:none;
  border-bottom:1px solid #b7b5b5;
  border-radius:0px;
  background:transparent;
}
.search-box.active ~ .search-results{
  visibility:visible;
}
.search-results {
  width: 100%;
  display: flex;
  flex-direction:column;
  align-items: center;
  height: 180px;
  background:#fff;
  border-radius: 30px;
  border: 1px solid #b7b5b5;
  visibility:hidden;
  margin-top:15px;
}

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

.links-container {
  width: 55%;
  height: 100%;
}  
 <nav>
  <div class="nav-container">
    <div class="search-container">
      <input class="search-box" id="search-box" type="search"  onkeyup="searching(this)" onfocus="fun(this)" placeholder="Please search fruits..">
      <div class="search-results" id="search-results">
        <div class="search-result">Apple</div>
        <div class="search-result">Mango</div>
        <div class="search-result">Orange</div>
        <div class="search-result">Grape</div>
        <div class="search-result">Watermelon</div>
      </div>
    </div>
    <div class="links-container"></div>
  </div>
</nav>  

Комментарии:

1. Спасибо за ответ! Я не использовал совсем это, но я приблизился к тому, что я ищу в моем исходном фрагменте. Я думаю, что наши подходы немного отличаются. Есть ли шанс, что у вас есть отзывы о моих обновлениях?