Размещение раскрывающегося списка уведомлений на кнопке

Я сделал эту концепцию: https://codepen.io/andrelange91/pen/yLpJRRw?editors=1100 В нем у меня есть значок колокольчика, который при нажатии показывает раскрывающийся список с уведомлениями. Но, в зависимости от размера экрана, он никогда не размещался со стрелкой в ​​раскрывающемся списке, указывающей на середину значка колокольчика.

Как я могу это сделать? Я немного заржавел, когда дело доходит до программирования внешнего интерфейса, и я не смог найти подходящих решений при его исследовании.

HTML

<ul class = "nav nav-pills nav-justified">
  <li class = "nav-item">
    <a class = "nav-link active" aria-current = "page" href = "#">Active</a>
  </li>
  <li class = "nav-item">
    <a class = "nav-link" href = "#">Much longer nav link</a>
  </li>
  <li class = "nav-item">
    <a class = "nav-link" href = "#">Link</a>
  </li>
  <li class = "nav-item notification-wrapper">
    <button class = "notification-button">
      <i class = "fas fa-bell"></i>
      <span>6</span>
    </button>
    <div class = "notification-popup">
      <div class = "notification-popup__header">
        <h3>Notifikationer</h3>
        <button title = "marker alle som læst"><i class = "fa-solid fa-check"></i></button>
      </div>
      <div class = "notification-item">
        <ul>
          <li><i class='far fa-newspaper'></i></li>
          <li>
            <h2>Ny side oprettet</h2>
            <p>Tjek den ud her!</p>
            <a href = "https://localhost:44310/medlem/nyheder/2022/nyhed-til-notification/">Nyhed til notification</a>
          </li>
          <li>
            <button class = "" title = "Makér denne som læst">
              <span><i class = "fas fa-check-circle"></i></span>
            </button>
          </li>
        </ul>
      </div>
      <div class = "notification-item">
        <ul>
          <li><i class='far fa-newspaper'></i></li>
          <li>
            <h2>Ny side oprettet</h2>
            <p>Tjek den ud her!</p>
            <a href = "https://localhost:44310/medlem/nyheder/2022/nyhed-til-notification/">Nyhed til notification</a>
          </li>
          <li>
            <button class = "" title = "Makér denne som læst">
              <span><i class = "fas fa-check-circle"></i></span>
            </button>
          </li>
        </ul>
      </div>
      <div class = "notification-item">
        <ul>
          <li><i class='far fa-newspaper'></i></li>
          <li>
            <h2>Ny side oprettet</h2>
            <p>Tjek den ud her!</p>
            <a href = "https://localhost:44310/medlem/nyheder/2022/nyhed-til-notification/">Nyhed til notification</a>
          </li>
          <li>
            <button class = "" title = "Makér denne som læst">
              <span><i class = "fas fa-check-circle"></i></span>
            </button>
          </li>
        </ul>
      </div>
      <div class = "notification-item">
        <ul>
          <li><i class='far fa-newspaper'></i></li>
          <li>
            <h2>Ny side oprettet</h2>
            <p>Tjek den ud her!</p>
            <a href = "https://localhost:44310/medlem/nyheder/2022/nyhed-til-notification/">Nyhed til notification</a>
          </li>
          <li>
            <button class = "" title = "Makér denne som læst">
              <span><i class = "fas fa-check-circle"></i></span>
            </button>
          </li>
        </ul>
      </div>
    </div>
  </li>
  <li class = "nav-item">
    <a class = "nav-link disabled">Disabled</a>
  </li>
</ul>

<nav>

</nav>

Стайлинг

$clr-white-1: #ecf0f1;
$clr-white-2: darken($clr-white-1, 5%);
$clr-t300: #444;
$clr-t500: #95a5a6;
$clr-p300: #111;
$clr-a300: #e74c3c; //#FF6A6A; //salmon
$container-shadow: 0.5rem 0.5rem 2rem 0 rgba(black, 0.2);
$h-gutter: 2rem;
$v-gutter: 0.75rem;

body {
  padding: 5% 0;
  margin: 0 0 50px 0;
  box-sizing: border-box;
  width: 100vw;
  height: 100vh;
  background: $clr-white-1;
  background: linear-gradient(30deg, $clr-white-2, $clr-white-1);
  font-family: "Lato", Arial, sans-serif;
  font-weight: 500;
  letter-spacing: 0.05rem;

  nav {
    position: absolute;
    left: 500px;
  }
}

.notification-wrapper {
  position: relative;
}

button.notification-button {
  position: relative;
  margin-right: 1em;
  border-radius: 5px;
  background: none;
  border: none;
  i {
    margin: 0.5rem;
  }
  &:nth-of-type(1) {
    i {
      background: -webkit-linear-gradient(300deg, #acccea, #6495ed);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
    }
  }
  &:nth-of-type(2) i {
    background: -webkit-linear-gradient(300deg, #fff9ab, #00b8ff);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
  }
  svg,
  .fa-bell {
    color: white;
    font-size: 28px;
  }
  span {
    position: absolute;
    user-select: none;
    cursor: default;
    font-size: 0.6rem;
    background: $clr-a300;
    width: 1.2rem;
    height: 1.2rem;
    color: $clr-white-1;
    display: inline-flex;
    justify-content: center;
    align-items: center;
    border-radius: 50%;
    top: -0.33rem;
    right: 0;
    box-sizing: border-box;

    animation-name: scaleCount;
    animation-iteration-count: 1;
    animation-timing-function: all;
    animation-duration: 1s;
    animation-delay: 0s;

    @keyframes scaleCount {
      0% {
        transform: scale(0);
      }
      40% {
        transform: scale(1);
      }
      60% {
        transform: scale(0.5);
      }
      80% {
        transform: scale(1.25);
      }
    }
  }
}
.notification-popup {
  display: none;
  &.active {
    display: block;
  }
  &:before {
    // triangle
    content: "";
    position: absolute;
    top: 1px;
    right: 0;
    width: 0;
    height: 0;
    transform: translate(-1rem, -100%);
    border-left: 0.75rem solid transparent;
    border-right: 0.75rem solid transparent;
    border-bottom: 0.75rem solid white;
  }
  cursor: default;
  position: absolute;
  z-index: 999;
  top: 56px;
  left: -210px;
  width: 400px;
  font-weight: 300;
  background: white;
  border-radius: 0.5rem;
  box-sizing: border-box;
  box-shadow: $container-shadow;

  animation-name: dropPanel;
  animation-iteration-count: 1;
  animation-timing-function: all;
  animation-duration: 0.75s;

  &__header {
    h3 {
      text-transform: uppercase;
      font-size: 75%;
      font-weight: 700;
      color: #84929f;
      padding: $v-gutter * 2 $h-gutter;
      display: inline-block;
    }
    button {
      float: right;
      border: none;
      background: none;
      i {
        text-transform: uppercase;
        font-size: 22px;
        font-weight: 700;
        padding: $v-gutter * 2 $h-gutter;
        color: #84929f;
      }
    }
  }
  .notification-item {
    border-bottom: 2px solid lightgrey;
    display: block;
    overflow: hidden;
    width: 100%;
    padding: 10px 0;
    ul {
      li {
        float: left;
        list-style: none;
        padding: 5px;
        position: relative;
        &:first-child {
          i {
            font-size: 22px;
          }
        }
        &:last-child {
          right: $h-gutter;
          margin-left: $v-gutter;
          float: right;
        }
        button {
          &:hover {
            opacity: 0.8;
            cursor: pointer;
          }
          span {
            color: #b5c4d2;
            font-size: 140%;
            top: 50%;
            -webkit-transform: translateY(-50%);
            -ms-transform: translateY(-50%);
            transform: translateY(-50%);
            position: absolute;
          }
          background: none;
          border: none;
        }
      }
    }
  }
}

@keyframes dropPanel {
  0% {
    opacity: 0;
    transform: translateY(-100px) scaleY(0.5);
  }
}

И для полноты картины мой js

$(".notification-button").on("click", function () {
  const ele = $(".notification-popup");
  if (ele.hasClass("active")) {
    console.info("remove active");
    ele.removeClass("active");
  } else {
    console.info("add active");
    ele.addClass("active");
  }
});
document.addEventListener(
  "click",
  function (event) {
    // If user either clicks X button OR clicks outside the modal window, then close modal by calling closeModal()
    if (
      event.target.closest(".notification-button") == null &&
      event.target.closest(".notification-popup") == null
    ) {
      console.info("remove active click outside");
      $(".notification-popup").removeClass("active");
    }
  },
  false
);

Не размещайте всплывающее окно с отрицательным значением left, а используйте right: 50%;вместо и добавьте transform: translateX(20px);, чтобы компенсировать примерно половину ширины кнопки. Или используйте translateX(1.25em), если вы хотите, чтобы размер шрифта оставался динамичным.

CBroe 21.03.2022 14:11

@CBroe, если вы добавите это в качестве ответа, я отмечу это правильно. Потому что это исправило это! Спасибо

andrelange91 21.03.2022 14:16
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
CSS: FlexBox
CSS: FlexBox
Ранее разработчики использовали макеты с помощью Position и Float. После появления flexbox сценарий полностью изменился.
0
2
26
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Попробуйте использовать .notification-popup{ transform: center top; }

Кажется, это ничего не делает. Вы пытались применить его на codepen самостоятельно, прежде чем предлагать?

andrelange91 21.03.2022 14:19

См. "Объяснение полностью основанных на коде ответов". Хотя это может быть технически правильным, это не объясняет, почему это решает проблему или должно быть выбранным ответом. Мы должны обучать, помогая решить проблему.

the Tin Man 22.03.2022 06:06
Ответ принят как подходящий

Не размещайте всплывающее окно с отрицательным значением left, а используйте right: 50%;вместо. Это выровняет правый угол с серединой li, содержащей кнопку.

А затем добавьте transform: translateX(20px);, чтобы компенсировать примерно половину ширины кнопки. Или используйте translateX(1.25em), если вы хотите, чтобы размер шрифта оставался динамичным.

Другие вопросы по теме

Вставка списка в раскрывающийся список сюжетных тире приводит к пустому раскрывающемуся списку
Как предотвратить перемещение выровненного по центру гибкого элемента по мере увеличения его высоты?
Как отключить определенное значение элемента выпадающего меню в флаттере
Как применить mixpanel при «срабатывании» события раскрывающегося списка в antdesign
Пользовательская созданная функция выпадающего списка по клику не срабатывает
Выпадающее меню из любой таблицы в базе данных - Laravel
Есть ли способ установить, когда выпадающий список начальной загрузки должен превратиться в выпадающий?
JQuery Если выбран раскрывающийся список
Как добавить список по умолчанию в раскрывающийся список, а затем использовать ввод поиска для фильтрации этого списка в отчете SSRS
Отображать выбранный вариант (другой href) в раскрывающемся заголовке