logo de l'entreprise

Construire un site web avec Frappe Builder - Partie 4 : Interactivité, JS, CSS

Global

html{

    scroll-behavior: smooth;

    overflow: scroll;

}

body {

    scroll-snap-type: y mandatory;

}

Navbar

.hover-underline-animation {

  display: inline-block;

  position: relative;

}

.hover-underline-animation::after {

  content: '';

  position: absolute;

  width: 100%;

  transform: scaleX(0);

  height: 2px;

  bottom: 0;

  left: 0;

  background-color: #875b5b;

  transition: transform 0.25s ease-out;

}

.hover-underline-animation:hover::after,

.hover-underline-animation.active::after {

  transform: scaleX(1);

}

/* Default state: transparent background */

.navbar-container {

  background-color: transparent;

  transition: background-color 0.6s ease-in-out;

}

.navbar-container.scrolled {

  background-color: #875b5b;

  opacity: 0.9;

}

document.addEventListener("scroll", () => {

  const navbar = document.querySelector(".navbar-container");

  if (window.scrollY > 0) {

    navbar.classList.add("scrolled");

  } else {

    navbar.classList.remove("scrolled");

  }

});

Filtres

.filterDiv {

    display: none;

}

.show {

    display: flex;

}

document.addEventListener("DOMContentLoaded", function () {

  // Function to filter elements based on the selected item group

  function filterSelection(c, section) {

    const divs = section.querySelectorAll(".filterDiv");

    if (c === "all") {

      // If "all" is selected, show all filterDiv elements

      divs.forEach(div => {

        if (!div.classList.contains("show")) {

          w3AddClass(div, "show");

        }

        w3RemoveClass(div, "hiding");

      });

      return; // Exit early if "all" is selected

    }

    // Loop through the divs to show/hide based on the item group filter

    divs.forEach(div => {

      const href = div.getAttribute("href");

      const itemGroup = href ? href.split("/")[1] : "";

      if (itemGroup === c) {

        // Show matching divs

        w3AddClass(div, "show");

        w3RemoveClass(div, "hiding");

      } else {

        // Temporarily add the "hiding" class for animations before hiding

        w3AddClass(div, "hiding");

        setTimeout(() => {

          w3RemoveClass(div, "show");

          w3RemoveClass(div, "hiding");

        }, 200); // Adjust the timeout duration to match your CSS animation duration

      }

    });

  }

  // Show filtered elements

  function w3AddClass(element, name) {

    const arr1 = element.className.split(" ");

    const arr2 = name.split(" ");

    for (let i = 0; i < arr2.length; i++) {

      if (arr1.indexOf(arr2[i]) === -1) {

        element.className += " " + arr2[i];

      }

    }

  }

  // Hide elements that are not selected

  function w3RemoveClass(element, name) {

    let arr1 = element.className.split(" ");

    const arr2 = name.split(" ");

    for (let i = 0; i < arr2.length; i++) {

      while (arr1.indexOf(arr2[i]) > -1) {

        arr1.splice(arr1.indexOf(arr2[i]), 1);

      }

    }

    element.className = arr1.join(" ");

  }

  // Event listener for button clicks (using event delegation for buttons in different containers)

  document.addEventListener("click", function (e) {

    // Check if the clicked element is a filter button

    const filterButton = e.target.closest(".filter-button");

    if (!filterButton) return; // Exit if clicked element is not a filter button

    // Find the closest filterSection that contains both buttons and filterDivs

    const filterSection = e.target.closest(".gallery");

    // Highlight the active button

    const current = filterSection.querySelectorAll(".active");

    current.forEach(btn => {

      btn.classList.remove("active");

    });

    filterButton.classList.add("active");

    // Get the text content of the button and use it as the filter value

    let filterValue = filterButton.querySelector("div").textContent.trim(); // Get the button text content

    // Special case for the button with 'all' class (show all divs)

    if (filterButton.classList.contains("all")) {

      filterValue = "all"; // If it's the "all" button, show all

    }

    // Get the filterDivContainer for this section

    const filterDivContainer = filterSection.querySelector(".filterDivContainer");

    // Call filterSelection to update the div visibility

    filterSelection(filterValue, filterDivContainer);

  });

});

Card Label

.overlay {

    transform: translateY(100%);

    transition: all 0.4s ease-in-out;

}

.filterDiv:hover .overlay{

    transform: translateY(0);

}

Mentions légales

Fait avec ❤️ par Antoine Maas Ingénierie en utilisant  Frappe Builder, outil no-code open source et gratuit pour la création de site web