Возникли проблемы с предотвращением дублирования кода CSS

У меня есть следующий фрагмент:

// Second Banner
document.addEventListener("DOMContentLoaded", function(event) {
  let executionFlag = true;
  const toastSecond = document.getElementById("toastSecond");

  const toastCloseSecond = document.getElementById("toastCloseSecond");



  window.onscroll = function(b) {
    const percentToScroll = 0.9; //0.9 of the page
    if (window.innerHeight + window.scrollY >= document.body.offsetHeight * percentToScroll && executionFlag) {


      toastSecond.classList.add("open1");
      executionFlag = false;
    }
  };

  toastCloseSecond.addEventListener("click", function() {
    toastSecond.classList.remove("open1");
  });

})

// First Banner
document.addEventListener("DOMContentLoaded", function(event) {

  (function() {
    requestAnimationFrame(function() {
      var banner;
      banner = document.querySelector('.exponea-banner');
      banner.classList.add('exponea-in');
      return banner.querySelector('.exponea-close').addEventListener('click', function() {
        return banner.classList.remove('exponea-in');
      });
    });

  }).call(this);
});
.exponea-banner {
  font-family: Roboto, sans-serif;
  position: fixed;
  right: 20px;
  bottom: 20px;
  background-color: #2e364d;
  color: #ebeef7;
  padding: 30px 80px 30px 35px;
  font-size: 16px;
  line-height: 1;
  border-radius: 5px;
  box-shadow: 0 3px 30px rgba(116, 119, 176, 0.3);
  opacity: 0;
  transition: opacity 0.2s;
  display: none;
}

.exponea-banner.exponea-in {
  opacity: 1;
  transition-duration: 0.4s;
}

.exponea-banner .exponea-close {
  position: absolute;
  top: 0;
  right: 0;
  padding: 5px 10px;
  font-size: 25px;
  font-weight: 300;
  cursor: pointer;
  opacity: 0.75;
}

.exponea-banner .exponea-label {
  position: absolute;
  bottom: 10px;
  right: 10px;
  font-size: 12px;
  opacity: 0.75;
}

.exponea-banner .exponea-text {
  margin-bottom: 8px;
}

.exponea-banner .exponea-count {
  opacity: 0.7;
  font-weight: 300;
  align-items: center;
  display: flex;
}

.exponea-banner .exponea-label {
  text-align: left;
  bottom: 10px;
  right: 10px;
  font-size: 12px;
  opacity: 0.75;
}

.exponea-banner,
.exponea-close,
.exponea-text,
.exponea-label,
.exponea-label {
  z-index: 999;
}

.open {
  display: block;
}


/* SecondBanner */

.exponea-banner1 {
  font-family: Roboto, sans-serif;
  position: fixed;
  right: 20px;
  bottom: 20px;
  background-color: #2e364d;
  color: #ebeef7;
  padding: 30px 80px 30px 35px;
  font-size: 16px;
  line-height: 1;
  border-radius: 5px;
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
  display: none;
  z-index: 9999999999;
}

.open1 {
  display: block;
}

.exponea-banner1 .exponea-close1 {
  position: absolute;
  top: 0;
  right: 0;
  padding: 5px 10px;
  font-size: 25px;
  font-weight: 300;
  cursor: pointer;
  opacity: 0.75;
}

.exponea-banner1 .exponea-label1 {
  position: absolute;
  bottom: 10px;
  right: 10px;
  font-size: 12px;
  opacity: 0.75;
}

.exponea-banner1 .exponea-text1 {
  margin-bottom: 8px;
}

.exponea-banner1 .exponea-count1 {
  font-weight: 500;
}

.exponea-banner1 .exponea-label1 {
  text-align: left;
  bottom: 10px;
  right: 10px;
  font-size: 12px;
  opacity: 0.75;
}

```
<!-- First banner -->
<div class = "exponea-banner open">
  <div class = "exponea-close">
    &times;
  </div>
  <div class = "exponea-text">
    Ex 1
  </div>
  <div class = "exponea-label">
    - user
  </div>
</div>

<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>

<!-- Second Banner -->
<div class = "exponea-banner1" id = "toastSecond">
  <div class = "exponea-close1" id = "toastCloseSecond">&times;</div>
  <div class = "exponea-text1"> Ex 2
  </div>
  <div class = "exponea-count"> some text</div>
  <div class = "exponea-label1">user</div>
</div>

Это в основном создает два одинаковых баннера. Первый баннер отображается, как только загружается страница, а второй баннер загружается в 0.9 страницы, как указано в JS.

Поскольку оба баннера абсолютно одинаковы, есть ли способ сократить CSS для него, чтобы единственная разница между двумя баннерами заключалась в том, как они себя ведут, например, в функциональности, когда один отображается в начале, а другой - 0,9 страницы. ?

Я в основном хочу избежать дублирования CSS

Я пытался сделать его общим, но тогда это портит файл JS, а затем второй баннер даже не загружается на экран.

Опубликованный код не меняет внешний вид, как вы описываете, после его запуска.

Mark Schultheiss 31.03.2023 00:58

Извините, просто отредактировано, чтобы представить визуальное

user16167303 31.03.2023 00:59
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
2
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я присвоил обоим баннерам одни и те же классы, поскольку оба имеют одинаковые свойства стиля и значения, и я добавил дополнительный attribute, который равен data-banner, а значения уникальны, и именно так мы можем выбрать их в JS.

Теперь у обоих баннеров есть две общие черты:
1- Они активируются
2- Они деактивируются, нажав кнопку закрытия

Единственная разница заключается в условии, когда он будет активирован.

Поэтому я создал две функции, одну для активации и одну для закрытия.
activeBanner и closeBanner, оба принимают 3 аргумента (элемент баннера, активный класс, закрытый элемент)

И еще две функции для обработки каждого баннера.
bannerOneHandler немедленно активирует баннер.
bannerTwoHandler активирует баннер на основе прокрутки.

Примечание:
Я вызвал обе функции в нижней части файла script. Но вы можете добавить событие для документа на DOMContentLoaded и переместить их в функцию события.

// Get the banners
var banner1 = document.querySelector('[data-banner = "first"]');
var banner2 = document.querySelector('[data-banner = "second"]');


const closeBanner = (banner, activeClass, closeEl) => {
  // Get "close" element and add the event to remove active class 
  let close = banner.querySelector(`.${closeEl}`)
  close.addEventListener('click', () => {
     banner.classList.remove(activeClass);
  });
}

const activeBanner = (banner, activeClass, closeEl) => {
   // Active the banner and call the closeBanner function
   banner.classList.add(activeClass);
   closeBanner(banner, activeClass, closeEl)
}


// Banner one handler
const bannerOneHandler = (banner) => {
  activeBanner(banner, 'open', 'exponea-close');
};
// Banner two handler
const bannerTwoHandler = (banner) => {
  let executionFlag = true;
  const percentToScroll = 0.9;
  
  window.addEventListener('scroll', () => {
    let windowHeightScroll = window.innerHeight + window.scrollY;
    let targetScroll = document.body.offsetHeight * percentToScroll

    if (windowHeightScroll >= targetScroll && executionFlag) {
      executionFlag = false;
      activeBanner(banner, 'open', 'exponea-close');
    }
  });
};


// Call the functions
bannerOneHandler(banner1)
bannerTwoHandler(banner2)
.exponea-banner {
  font-family: Roboto, sans-serif;
  position: fixed;
  right: 20px;
  bottom: 20px;
  background-color: #2e364d;
  color: #ebeef7;
  padding: 30px 80px 30px 35px;
  font-size: 16px;
  line-height: 1;
  border-radius: 5px;
  box-shadow: 0 3px 30px rgba(116, 119, 176, 0.3);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s;
  transition-delay: 0.2s;
}

.exponea-banner .exponea-close {
  position: absolute;
  top: 0;
  right: 0;
  padding: 5px 10px;
  font-size: 25px;
  font-weight: 300;
  cursor: pointer;
  opacity: 0.75;
}

.exponea-banner .exponea-label {
  position: absolute;
  bottom: 10px;
  right: 10px;
  font-size: 12px;
  opacity: 0.75;
}

.exponea-banner .exponea-text {
  margin-bottom: 8px;
}

.exponea-banner .exponea-count {
  opacity: 0.7;
  font-weight: 300;
  align-items: center;
  display: flex;
}

.exponea-banner .exponea-label {
  text-align: left;
  bottom: 10px;
  right: 10px;
  font-size: 12px;
  opacity: 0.75;
}

.exponea-banner,
.exponea-close,
.exponea-text,
.exponea-label,
.exponea-label {
  z-index: 999;
}

.open {
  visibility: visible;
  opacity: 1;
}
<!-- First banner -->
<div class = "exponea-banner" data-banner = "first">
  <div class = "exponea-close">
    &times;
  </div>
  <div class = "exponea-text">
    Hi There! Thanks For Stumbling Upon My Website!
  </div>
  <div class = "exponea-label">
    - Hussain Omer
  </div>
</div>

<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>
<div> some content </div>

<!-- Second Banner -->
<div class = "exponea-banner" data-banner = "second">
  <div class = "exponea-close">&times;</div>
  <div class = "exponea-text"> Thanks For Visiting!
  </div>
  <div class = "exponea-count"> Feel Free To Contact Me!</div>
  <div class = "exponea-label">- Hussain Omer</div>
</div>

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