Create Responsive Card Layout with HTML, CSS, and JavaScript (Source Code)


By Faraz -

Learn how to create a responsive card layout using HTML, CSS, and JavaScript. Step-by-step tutorial for building interactive cards in web development. Source code included.

create responsive card layout with html, css, and javascript (source code).jpg

In today's rapidly evolving digital landscape, creating visually appealing and user-friendly websites is crucial for success. One important aspect of modern web design is the implementation of responsive card layouts. Responsive card layouts provide a flexible and adaptive way to present information, images, and interactive elements on a webpage, ensuring optimal user experience across various devices and screen sizes.

In this comprehensive tutorial, we will guide you through the process of creating a responsive card layout using HTML, CSS, and JavaScript. Whether you're a beginner looking to enhance your web development skills or an intermediate developer aiming to improve your front-end design techniques, this tutorial is designed to help you achieve your goals.

Why are responsive card layouts important? As users increasingly access websites on smartphones, tablets, and various other devices, it becomes crucial for web developers to ensure their designs adapt seamlessly to different screen sizes. Responsive card layouts provide a solution by organizing content into visually appealing and easily digestible sections, allowing users to navigate and interact with the website effortlessly.

HTML, CSS, and JavaScript form the backbone of modern web development. HTML (Hypertext Markup Language) defines the structure and content of a webpage, CSS (Cascading Style Sheets) determines the visual presentation and layout, while JavaScript adds interactivity and enhances the user experience. By leveraging these three fundamental technologies, you will learn how to create stunning and responsive card layouts that engage and captivate your website visitors.

Throughout this tutorial, we will provide step-by-step instructions, along with relevant code snippets, to ensure you grasp the concepts and implementation details. By the end of the tutorial, you will have the knowledge and skills to design and build your own responsive card layouts, tailored to meet the specific needs of your web projects.

So, let's dive into the world of responsive card layouts and unlock the potential to create visually stunning, interactive, and user-friendly web experiences. Get ready to elevate your web development skills and embark on an exciting journey of designing modern, responsive card layouts with HTML, CSS, and JavaScript.

Credit: Ryan Yu

Source Code

Step 1 (HTML Code):

To get started, we will first need to create a basic HTML file. In this file, we will include the main structure for our card layout.

After creating the files just paste the following codes into your file. Make sure to save your HTML document with a .html extension, so that it can be properly viewed in a web browser.

Let's break it down step by step:

The first line <!DOCTYPE html> declares the document type as HTML5.

The <html> tag is the root element of an HTML page.

The lang="en" attribute in the <html> tag specifies the language of the document as English.

The <head> element contains meta-information about the HTML document and defines its title, character encoding, and viewport settings.

  • The <title> element sets the title of the page, which appears in the browser's title bar or tab.
  • The <meta charset="UTF-8" /> specifies the character encoding for the document as UTF-8, which supports a wide range of characters.
  • The <meta name="viewport" content="width=device-width" /> sets the viewport width to the width of the device, ensuring proper rendering on mobile devices.
  • The <link rel="stylesheet" href="styles.css" /> links an external CSS file named "styles.css" to the HTML document for styling purposes.

The <body> element represents the content of the HTML document that will be displayed in the browser.

Inside the body, there is a <div> element with the class "c-magic-area c-magic-area--content". It seems to be related to some kind of interactive content but without further information, its purpose is unclear.

The next section is a <section> element with the class "o-main-section". This section contains multiple articles, each representing a card in the layout.

Each card is represented by an <article> element with the class "c-article".

  • Inside each article, there is an anchor <a> element with the class "c-article__link" and an empty href attribute "#". This creates a clickable link without navigating to a specific URL.
  • Inside the anchor element, there are two <div> elements and an <img> element.
  • The first <div> contains a <header> element with a <h3> heading element inside it. This represents the title or heading of the article.
  • The second <div> represents the content of the article.
  • The <img> element displays an image related to the article. It has the class "c-article__img" and the source (src) attribute pointing to an external image file.

After the section, there are two <script> elements.

  • The first script imports a JavaScript library called GSAP (GreenSock Animation Platform) from a CDN (content delivery network) using the specified URL.
  • The second script imports a JavaScript file named "script.js" from the local directory. The purpose of this script is not clear without examining its content.

This is the basic structure of our card layout indicator using HTML, and now we can move on to styling it using CSS.

Step 2 (CSS Code):

Once the basic HTML structure of the card is in place, the next step is to add styling to the card layout using CSS.

Next, we will create our CSS file. In this file, we will use some basic CSS rules to create our card layout.

Let's go through it step by step:

The code starts with a general styling for the entire webpage. The background color is set to white (#fff), the text color is set to a dark gray (#404040), and the font family is set to "Open Sans" with a fallback to sans-serif.

The .o-main-section class is defined next. It is used to style a main section of the webpage. It sets the left and right margins to "auto" (automatically centering the section horizontally) and restricts the maximum width to 37.5rem.

The .c-article__link class is used to style links within articles. It aligns the link's content vertically in the center, sets the text color to #404040, displays the link as a flex container, justifies the content with space between (pushing the elements apart), adds some top and bottom margin (1.875rem) and padding (1.25rem), and removes the text decoration (underlining by default). The * selector within .c-article__link disables pointer events for all elements inside the link.

The .c-article__heading class defines the styling for headings within articles. It sets the font size to 1.25rem and adds some top and bottom margin (0.625rem).

The .c-article__content class is used to style the content paragraphs within articles. It sets the line height to 1.5 (creating some spacing between lines) and adds some top and bottom margin (0.625rem).

The .c-article__img-wrapper class is used to style a container element for images within articles. It sets the height to 6.25rem, adds some left margin (1.25rem), sets the minimum width to 10rem, and sets the width to 10rem.

The .c-article__img class is used to style images within articles. It sets the border radius to 0.125rem (creating rounded corners), displays the image as a block element, sets the height to 100% of the parent container, applies a grayscale filter to make the image black and white, sets the object-fit property to cover (maintaining the aspect ratio while covering the container), applies a smooth transition effect for the filter property (0.3s ease-in), and sets the width to 100% of the parent container. The .c-article__link:hover .c-article__img selector specifies that when hovering over the link containing the image, the grayscale filter should be removed (setting it to grayscale(0)).

The .c-magic-area class is used to define a magic area, positioned absolutely and with a lower z-index. It is often used for special effects or overlays.

The .c-magic-area--content class is used to style the content within the magic area. It sets the background color to a semi-transparent gray (rgba(64, 64, 64, 0.15)) and adds a border radius of 0.125rem (creating rounded corners).

The .c-magic-area--content::before selector is used to create a vertical bar before the content within the magic area. It sets the background color to #404040 (dark gray), creates an empty content before pseudo-element, sets its height to 70% of the magic area's height, positions it absolutely to the left with a slight overlap (-0.1875rem), centers it vertically (using a translation), and sets its width to 0.375rem.

This will give our card layout an upgraded presentation. Create a CSS file with the name of styles.css and paste the given codes into your CSS file. Remember that you must create a file with the .css extension.

body {
  background-color: #fff;
  color: #404040;
  font-family: "Open Sans", sans-serif;

.o-main-section {
  margin: 0 auto;
  max-width: 37.5rem;

.c-article__link {
  align-items: center;
  color: #404040;
  display: flex;
  justify-content: space-between;
  margin: 1.875rem 0;
  padding: 1.25rem;
  text-decoration: none;
.c-article__link * {
  pointer-events: none;

.c-article__heading {
  font-size: 1.25rem;
  margin: 0.625rem 0;

.c-article__content {
  line-height: 1.5;
  margin: 0.625rem 0;

.c-article__img-wrapper {
  height: 6.25rem;
  margin-left: 1.25rem;
  min-width: 10rem;
  width: 10rem;

.c-article__img {
  border-radius: 0.125rem;
  display: block;
  height: 100%;
  filter: grayscale(1);
  -o-object-fit: cover;
     object-fit: cover;
  transition: filter 0.3s ease-in;
  width: 100%;
.c-article__link:hover .c-article__img {
  filter: grayscale(0);

.c-magic-area {
  position: absolute;
  z-index: -1;

.c-magic-area--content {
  background-color: rgba(64, 64, 64, 0.15);
  border-radius: 0.125rem;
.c-magic-area--content::before {
  background-color: #404040;
  content: "";
  height: 70%;
  left: -0.1875rem;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 0.375rem;

Step 3 (JavaScript Code):

Finally, we need to create a function in JavaScript.

Let's go through the code step by step and explain its functionality:

The first line of code selects all elements with the class "c-magic-area" using the querySelectorAll method and stores them in the magicAreas constant as an array.

The getAreaDetails function takes an area parameter, which represents a DOM element. It retrieves various details about the element such as its width, height, position, and offset from the top and left of the viewport. These details are calculated using the clientWidth, clientHeight, and getBoundingClientRect methods. The function then returns an object containing these details.

The setTweenArea function is responsible for setting the initial position and dimensions of a "magic area" element. It takes two parameters: link represents a DOM element (presumably a link) and magicArea represents a "magic area" element. The function retrieves the area details of the link using the getAreaDetails function and uses the gsap.set method to set the top, left, width, and height CSS properties of the magicArea element accordingly.

The tweenMagicArea function is similar to setTweenArea, but instead of setting the initial position, it animates the movement of the "magic area" element to a new position and dimensions. The target parameter represents the target DOM element (again, presumably a link), and magicArea represents the "magic area" element. It retrieves the area details of the target using getAreaDetails and uses the gsap.to method to animate the left, top, width, and height properties of the magicArea element over a duration of 0.5 seconds.

The getMagicActiveElement function takes an array of links (DOM elements) as input and filters them to return an array of elements that meet certain conditions. However, the implementation of this function is incomplete, as the filtering logic is missing.

The moveMagicArea function is responsible for attaching event listeners to the links elements to trigger the animation of the "magic area" element when certain events occur. It takes three parameters: links represents an array of DOM elements, magicArea represents the "magic area" element, and isTweenBack is a boolean flag indicating whether the animation should revert back to its original state. The function iterates over the links array using the map method and adds event listeners for the mouseenter, focus, mouseleave, and focusout events. When these events occur, the corresponding event handlers call the tweenMagicArea function to animate the magicArea element based on the target element (e.target).

The setMagic function is responsible for setting up the initial state of the "magic area" element based on the currently active element or the first element in the links array. It takes two parameters: links represents an array of DOM elements, and magicArea represents the "magic area" element. The function first calls the getMagicActiveElement function to check if there are any active elements in the links array. If there are active elements, it calls setTweenArea to set the initial position and dimensions of the magicArea based on the first active element. If there are no active elements, it simply calls setTweenArea using the first element in the links array.

The initMagic function serves as the main entry point for initializing the "magic" effect. It takes an optional object parameter { isResize } with a default value of { isResize: false }. The function first checks if there are any magicAreas available by checking the length of the magicAreas array. If there are no magicAreas, the function returns early and does nothing. Otherwise, it iterates over the magicAreas array using the map method.

Inside the loop, it retrieves the data-target-class attribute value from the current magicArea element. This attribute is expected to contain a CSS selector that identifies the target elements for the "magic" effect. It then uses document.querySelectorAll to select all elements matching the given CSS selector and stores them in the links array.

If there are no links found for the current magicArea, the function returns early and moves to the next magicArea in the loop.

If links are found, the function calls setMagic to set up the initial state of the "magic area" element based on the active element or the first element in the links array.

If isResize is false (or not provided), indicating that the function is not triggered by a resize event, it retrieves the value of the data-tween-back attribute from the magicArea element. If the value is "true", it sets the isTweenBack variable to true; otherwise, it sets it to false. The moveMagicArea function is then called with links, magicArea, and isTweenBack as parameters to attach event listeners and enable the "magic" effect.

Finally, outside the loop, the initMagic function is called without any arguments to start the initialization process.

There is a commented-out function onResize that is not currently being used. It seems to be intended to handle the logic for the "magic" effect when a resize event occurs.

Create a JavaScript file with the name of script.js and paste the given codes into your JavaScript file and make sure it's linked properly to your HTML document, so that the scripts are executed on the page. Remember, you’ve to create a file with .js extension.

const magicAreas = [...document.querySelectorAll(".c-magic-area")];

const getAreaDetails = (area) => {
  const width = area.clientWidth;
  const height = area.clientHeight;

  const position = area.getBoundingClientRect();
  const top = position.top + window.scrollY;
  const left = position.left;
  return {

const setTweenArea = (link, magicArea) => {
  const { left, height, top, width } = getAreaDetails(link);

  gsap.set(magicArea, {

const tweenMagicArea = (target, magicArea) => {
  const { left, height, top, width } = getAreaDetails(target);

  gsap.to(magicArea, 0.5, {
    ease: Power3.easeInOut

const getMagicActiveElement = (links) => {
  return links.filter((link) => {

const moveMagicArea = (links, magicArea, isTweenBack) => {
  const magicActiveElement = getMagicActiveElement(links);

  links.map((link) => {
    link.addEventListener("mouseenter", function (e) {
      tweenMagicArea(e.target, magicArea);

    link.addEventListener("focus", function (e) {
      tweenMagicArea(e.target, magicArea);

    if (isTweenBack && magicActiveElement.length) {
      link.addEventListener("mouseleave", function (e) {
        tweenMagicArea(magicActiveElement[0], magicArea);

      link.addEventListener("focusout", function (e) {
        tweenMagicArea(magicActiveElement[0], magicArea);

const setMagic = (links, magicArea) => {
  // check if .is-magic-active || aria-current="page"
  const magicActiveElement = getMagicActiveElement(links);

  if (magicActiveElement.length) {
    setTweenArea(magicActiveElement[0], magicArea);
  } else {
    setTweenArea(links[0], magicArea);

const initMagic = ({ isResize } = { isResize: false }) => {
  if (!magicAreas.length) return;

  magicAreas.map((magicArea) => {
    const targetMagicArea = magicArea.getAttribute("data-target-class");

    const links = [...document.querySelectorAll(targetMagicArea)];

    if (!links.length) return;

    setMagic(links, magicArea);

    if (!isResize) {
      const isTweenBack = magicArea.getAttribute("data-tween-back") === "true";

      moveMagicArea(links, magicArea, isTweenBack);


Final Output:

create responsive card layout with html, css, and javascript (source code).gif


Congratulations! You have successfully learned how to create a responsive card layout using HTML, CSS, and JavaScript. Throughout this tutorial, we covered the essential steps and provided you with the necessary knowledge and code snippets to implement stunning and interactive card layouts for your web projects.

By understanding the importance of responsive design and leveraging the power of HTML, CSS, and JavaScript, you now have the ability to adapt your web layouts to different screen sizes and devices. This ensures that your website provides an optimal user experience, regardless of whether visitors access it from a desktop computer, tablet, or smartphone.

Remember, a well-designed card layout not only enhances the visual appeal of your website but also improves the usability and accessibility for your users. By organizing content into visually distinct and manageable sections, you allow users to quickly scan and find the information they need, leading to a more engaging and satisfying user experience.

As you continue your journey in web development, we encourage you to explore further and customize your card layouts to suit your unique needs and creative vision. Experiment with different CSS properties, animation effects, and interactivity using JavaScript to make your card layouts truly stand out.

Additionally, don't forget to test and optimize your card layouts for cross-browser compatibility and performance. Regularly check your designs on various browsers and devices to ensure consistent functionality and visual appeal. Implementing optimization techniques such as minifying code, compressing images, and leveraging browser caching can significantly improve the loading speed of your website, further enhancing the user experience.

With the knowledge and skills gained from this tutorial, you now have the foundation to create compelling and responsive card layouts that will captivate your website visitors and leave a lasting impression. Embrace creativity, stay updated with the latest web design trends, and continue to refine your skills to create exceptional web experiences.

Thank you for joining us on this journey of learning and discovery. We hope this tutorial has empowered you to take your web development skills to new heights. Happy coding and best of luck with your future projects!

That’s a wrap!

I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.

Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee.

And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!

Faraz 😊

End of the article

Subscribe to my Newsletter

Get the latest posts delivered right to your inbox

Latest Post