<header>
  <div class="container header-content">
    <img alt="envato-tuts+" class="logo" src="https://static.tutsplus.com/packs/media/images/tuts_logo-ae9e557ae6c08db82f47e6047900e39b.svg">

    <div class="search-bar">
      <input id="search" type="search" placeholder="&#x1F50D; Start typing to search..." list="search-suggestions" autocomplete="off"/>
      
      <datalist id="search-suggestions">
        <option value="JavaScript">
        <option value="CSS">
        <option value="Accessibility">
        <option value="Web Design">
      </datalist>
    </div>
  </div>
</header>

<main class="container">
  <div class="profile__posts">
    <div class="search-display"></div>
    <div class="card-header">
      <div class="card-header__title">Tutorials</div>
    </div>
    <div class="posts-container">
    </div>
  </div>
</main>
* {
  box-sizing: border-box;
}

body {
  font: normal 16px/26px system-ui, Roboto, Arial, sans-serif;
  background: #fefefe;
  color: #2a3744;
  margin: 0;
  padding: 0;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: none;
  overflow-x: hidden;
}

header {
  background: #282828;
  position: relative;
  font-family: system-ui, Roboto, sans-serif;
  min-height: 75px;
  display: flex;
  align-items: center;
  position: sticky;
  top: -54px;
  z-index: 2;
}

.logo {
  height: 24px;
}

a {
  color: #0085b6;
  text-decoration: none;
  border: none;
}

.container {
  max-width: 1440px;
  margin: 0 auto;
  padding: 24px 24px 0px;
  width: 100%;
}

.search-bar {
  display: flex;
  justify-content: center;
  padding: 24px;
}

.search-bar input {
  width: 50%;
  min-width: 300px;
  padding: 12px 24px;
  border-radius: 24px;
  font-size: 16px;
  border: 0px;
  outline: none;
}

.search-bar [list]::-webkit-list-button,
.search-bar [list]::-webkit-calendar-picker-indicator {
  display: none !important;
}

.search-display {
  text-align: center;
}

.card-header__title {
  font-weight: 700;
  font-size: 14px;
  color: #8fa6b3;
}

.posts-container {
  display: flex;
  flex-wrap: wrap;
  gap: 30px;
  padding: 12px 0;
}

.post {
  position: relative;
  min-width: 300px;
  flex: 0 0 25%;
  border: 1px solid #e1e8ed;
  border-radius: 4px;
  min-height: 300px;
  height: auto;
}

.post-title {
  font: 700 18px/1.4em system-ui, Roboto, Arial, sans-serif;
  color: #4a4a4a;
  margin-top: 0;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}

.post-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
}

.post-content {
  padding: 16px;
}

.post-preview {
  overflow: hidden;
  width: 100%;
  text-align: center;
  display: block;
  margin: 0 auto;
  border-bottom: 1px solid #e1e8ed;
  line-height: 0;
  height: 200px;
}

.post-tag {
  display: inline-block;
  margin-right: 10px;
  margin-bottom: 10px;
  padding: 0 8px;
  color: #717171;
  border: 1px solid #9b9b9b;
  border-radius: 25px;
  white-space: nowrap;
}

.filter-container {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: 10px;
  padding: 32px 0;
  border-top: 1px solid #e4e4e4;
  border-bottom: 1px solid #e4e4e4;
  margin-bottom: 32px;
}

.filter-button {
  transition: background-color 200ms, color 200ms;
  background-color: transparent;
  font: inherit;
  cursor: pointer;
  display: inline-block;
  padding: 0 8px;
  color: #717171;
  border: 1px solid #9b9b9b;
  border-radius: 25px;
  font-size: 14px;
  white-space: nowrap;
}

.filter-button:hover {
  background-color: #f3f3f3;
  color: #3a3a3a;
}

.filter-button.is-active {
  background-color: #0085b6;
  border-color: #0085b6;
  color: #fff;
}
let postsData = "";
const postsContainer = document.querySelector(".posts-container");
const searchDisplay = document.querySelector(".search-display");

fetch(
  "https://gist.githubusercontent.com/jemimaabu/564beec0a30dbd7d63a90a153d2bc80b/raw/0b7e25ba0ebee6dbba216cfcfbae72d460a60f26/tutorial-levels"
).then(async (response) => {
  postsData = await response.json();
  postsData.map((post) => createPost(post));
});

const createPost = (postData) => {
  const { title, link, image, categories } = postData;
  const post = document.createElement("div");
  post.className = "post";
  post.innerHTML = `
      <a class="post-preview" href="${link}" target="_blank">
        <img class="post-image" src="${image}">
      </a>
      <div class="post-content">
        <p class="post-title">${title}</p>
        <div class="post-tags">
          ${categories
            .map((category) => {
              return '<span class="post-tag">' + category + "</span>";
            })
            .join("")}
        </div>
      </div>
  `;

  postsContainer.append(post);
};

const handleSearchPosts = (query) => {
  const searchQuery = query.trim().toLowerCase();
  
  if (searchQuery.length <= 1) {
    resetPosts()
    return
  }
  
  let searchResults = [...postsData].filter(
    (post) =>
      post.categories.some((category) => category.toLowerCase().includes(searchQuery)) ||
      post.title.toLowerCase().includes(searchQuery)
  );
  
  if (searchResults.length == 0) {
    searchDisplay.innerHTML = "No results found"
  } else if (searchResults.length == 1) {
    searchDisplay.innerHTML = `1 result found for your query: ${query}`
  } else {
    searchDisplay.innerHTML = `${searchResults.length} results found for your query: ${query}`
  }

  postsContainer.innerHTML = "";
  searchResults.map((post) => createPost(post));
};

const resetPosts = () => {
  searchDisplay.innerHTML = ""
  postsContainer.innerHTML = "";
  postsData.map((post) => createPost(post));
};

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

let debounceTimer;
const debounce = (callback, time) => {
  window.clearTimeout(debounceTimer);
  debounceTimer = window.setTimeout(callback, time);
};

search.addEventListener(
  "input",
  (event) => {
    const query = event.target.value;
    debounce(() => handleSearchPosts(query), 500);
  },
  false
);

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css

External JavaScript

This Pen doesn't use any external JavaScript resources.