Learn how to create a responsive medical landing page using HTML, CSS, and JavaScript. Follow our step-by-step guide for the best practices in healthcare website design.
Table of Contents
Creating a responsive medical landing page is essential for healthcare providers. Patients increasingly rely on online resources to find medical information, book appointments, and interact with healthcare providers online. Creating a responsive landing page ensures that your website is accessible and user-friendly on all devices, from smartphones to desktops. This guide will walk you through the process of building a responsive medical landing page using HTML, CSS, and JavaScript, helping you provide the best online experience for your patients.
Source Code
Step 1 (HTML Code):
Before diving into coding, set up your project environment. Create a new directory for your project and initialize it with basic HTML, CSS, and JavaScript files. Organize your files into separate folders for easier management. For instance, create an "index.html" file for your main structure, a "style.css" file for your styles, and a "script.js" file for your interactive features. This setup will help you keep your project organized and manageable as it grows.
Building the Structure with HTML
Start by creating the basic structure of your landing page using HTML. We'll start with a well-organized markup. After creating the files just paste the following codes into your html file. Let's break down each part:
<html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Health and Medical Landing Page</title> <meta name="title" content="Doclab - home"> <meta name="description" content="This is a madical html template made by codewithsadee"> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Oswald:wght@500;700&family=Rubik:wght@400;500;700&display=swap" rel="stylesheet"> <link rel="stylesheet" href="styles.css"> </head> <body id="top">
<!DOCTYPE html>
: Declares the document type and version of HTML.<html lang="en">
: Defines the root element of the document with English as the language.<head>
: Contains metadata and links to external resources.<meta charset="UTF-8">
: Sets the character encoding to UTF-8.<meta http-equiv="X-UA-Compatible" content="IE=edge">
: Instructs IE to use the latest rendering engine.<meta name="viewport" content="width=device-width, initial-scale=1.0">
: Sets the viewport to the device's width and scale.<title>
Health and Medical Landing Page</title>
: Sets the title of the webpage.<meta name="title" content="Doclab - home">
: Metadata for SEO, specifying the title.<meta name="description" content="This is a medical html template made by codewithsadee">
: Metadata for SEO, providing a description.<link rel="preconnect" href="https://fonts.googleapis.com">
and<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
: Preconnects to Google Fonts to improve loading speed.<link href="https://fonts.google....;" rel="stylesheet">
: Loads external fonts (Oswald and Rubik) from Google Fonts.<link rel="stylesheet" href="styles.css">
: Links to an external stylesheet (styles.css).
<div class="preloader" data-preloader> <div class="circle"></div> </div> <header class="header" data-header> <div class="container"> <!-- Logo and navigation --> </div> </header>
<div class="preloader" data-preloader>
: Placeholder for a preloader (loading animation) which is commonly used in web applications.<header class="header" data-header>
: Defines the header section of the webpage.<div class="container">
: Wraps the content within a container for better layout control.
Within the header:
- Logo and navigation elements are defined, including a responsive menu (hamburger icon for mobile) and social media icons.
<main> <article> <section class="section hero" style="background-image: url('https://raw.githubusercontent.com/farazc60/Project-Images/main/medical/assets/hero-bg.png')" aria-label="home"> <div class="container"> <div class="hero-content"> <!-- Hero content including title, subtitle, search form --> </div> <figure class="hero-banner"> <img src="https://raw.githubusercontent.com/farazc60/Project-Images/main/medical/assets/hero-banner.png" width="590" height="517" loading="eager" alt="hero banner"> </figure> </div> </section> <section class="service" aria-label="service"> <div class="container"> <ul class="service-list"> <!-- List of service sections, each with an icon, title, description, and link --> </ul> </div> </section> <section class="section about" aria-labelledby="about-label"> <div class="container"> <div class="about-content"> <!-- About section with title, subtitle, description, and list --> </div> <figure class="about-banner"> <img src="https://raw.githubusercontent.com/farazc60/Project-Images/main/medical/assets/about-banner.png" width="554" height="678" loading="lazy" alt="about banner"> </figure> </div> </section> <section class="section listing" aria-labelledby="listing-label"> <div class="container"> <ul class="grid-list"> <!-- Listing section with titles and cards for different specialist categories --> </ul> </div> </section> <section class="section blog" aria-labelledby="blog-label"> <div class="container"> <p class="section-subtitle title-lg text-center" id="blog-label"> <!-- Blog section title --> </p> <h2 class="section-title headline-md text-center"> <!-- Blog section subtitle --> </h2> <ul class="grid-list"> <!-- Blog cards with meta information, title, date, and excerpt --> </ul> </div> </section> </article> </main>
Hero Section (<section class="section hero">
):
- This section serves as the introductory area with a background image (hero-bg.png).
- Inside, there's a container with hero-content, which includes a welcome message (hero-subtitle), a main headline (hero-title), and a search form (hero-card) to find doctors or medical services.
- A hero-banner figure displays an image (hero-banner.png) related to the hero section.
Service Section (<section class="service">
):
- This section lists different medical services (service-list) available, each represented by a service-card. Each card includes an icon, title (card-title), brief description (card-text), and a button to read more (btn-circle).
About Section (<section class="section about">
):
- Provides information about the organization (about-content). It includes a title (section-subtitle), a headline (headline-md), a description (section-text), and a list (about-list) detailing key points about the organization.
- A figure (about-banner) displays an image (about-banner.png) related to the about section.
Listing Section (<section class="section listing">
):
- Lists different specialist categories (grid-list) available, each represented by a listing-card. Each card includes an icon, title, and a brief description.
Blog Section (<section class="section blog">
):
- Provides the latest articles (grid-list) related to the medical field. Each article (blog-card) includes meta information (card-meta), title (card-title), publication date (date), and an excerpt (card-text). Each card also has a button (btn-text) to read more.
Footer Structure:
<footer class="footer" style="background-image: url('https://raw.githubusercontent.com/farazc60/Project-Images/main/medical/assets/footer-bg.png')"> <div class="container"> <div class="section footer-top"> <!-- Footer top section containing branding, contact information, about us, services, subscribe --> <div class="footer-brand" data-reveal="bottom"> <a href="#" class="logo"> <img src="https://raw.githubusercontent.com/farazc60/Project-Images/main/medical/assets/logo.svg" width="136" height="46" loading="lazy" alt="Doclab home"> </a> <ul class="contact-list has-after"> <!-- Contact information --> <li class="contact-item"> <div class="item-icon"> <ion-icon name="mail-open-outline"></ion-icon> </div> <div> <p>Main Email : <a href="mailto:[email protected]" class="contact-link">contact@website.com</a></p> <p>Inquiries : <a href="mailto:[email protected]" class="contact-link">[email protected]</a></p> </div> </li> <li class="contact-item"> <div class="item-icon"> <ion-icon name="call-outline"></ion-icon> </div> <div> <p>Office Telephone : <a href="tel:0029129102320" class="contact-link">0029129102320</a></p> <p>Mobile : <a href="tel:000232439493" class="contact-link">000 2324 39493</a></p> </div> </li> </ul> </div> <div class="footer-list" data-reveal="bottom"> <!-- About Us section --> <p class="headline-sm footer-list-title">About Us</p> <p class="text"> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed </p> <address class="address"> <ion-icon name="map-outline"></ion-icon> <span class="text"> 2416 Mapleview Drive <br> Tampa, FL 33634 </span> </address> </div> <ul class="footer-list" data-reveal="bottom"> <!-- Services links --> <li><p class="headline-sm footer-list-title">Services</p></li> <li><a href="#" class="text footer-link">Conditions</a></li> <li><a href="#" class="text footer-link">Listing</a></li> <li><a href="#" class="text footer-link">How It Works</a></li> <li><a href="#" class="text footer-link">What We Offer</a></li> <li><a href="#" class="text footer-link">Latest News</a></li> <li><a href="#" class="text footer-link">Contact Us</a></li> </ul> <ul class="footer-list" data-reveal="bottom"> <!-- Useful Links section --> <li><p class="headline-sm footer-list-title">Useful Links</p></li> <li><a href="#" class="text footer-link">Conditions</a></li> <li><a href="#" class="text footer-link">Terms of Use</a></li> <li><a href="#" class="text footer-link">Our Services</a></li> <li><a href="#" class="text footer-link">Join as a Doctor</a></li> <li><a href="#" class="text footer-link">New Guests List</a></li> <li><a href="#" class="text footer-link">The Team List</a></li> </ul> <div class="footer-list" data-reveal="bottom"> <!-- Subscribe section --> <p class="headline-sm footer-list-title">Subscribe</p> <form action="" class="footer-form"> <input type="email" name="email" placeholder="Email" class="input-field title-lg"> <button type="submit" class="btn has-before title-md">Subscribe</button> </form> <p class="text"> Get the latest updates via email. Any time you may unsubscribe </p> </div> </div> <div class="footer-bottom"> <!-- Footer bottom section with copyright and social links --> <p class="text copyright"> © Doclab 2022 | All Rights Reserved by codewithsadee </p> <ul class="social-list"> <li><a href="#" class="social-link"><ion-icon name="logo-facebook"></ion-icon></a></li> <li><a href="#" class="social-link"><ion-icon name="logo-twitter"></ion-icon></a></li> <li><a href="#" class="social-link"><ion-icon name="logo-google"></ion-icon></a></li> <li><a href="#" class="social-link"><ion-icon name="logo-linkedin"></ion-icon></a></li> <li><a href="#" class="social-link"><ion-icon name="logo-pinterest"></ion-icon></a></li> </ul> </div> </div> </footer> <a href="#top" class="back-top-btn" aria-label="back to top" data-back-top-btn> <ion-icon name="chevron-up"></ion-icon> </a> <script src="script.js"></script> <script type="module" src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.esm.js"></script> <script nomodule src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.js"></script>
Footer (<footer class="footer">
):
- This section defines the footer area of the webpage, with a background image (footer-bg.png).
Container (<div class="container">
):
- Contains all footer content, ensuring it is neatly organized and centered.
Footer Top (<div class="section footer-top">
):
- Contains multiple sections:
- Footer Brand (
<div class="footer-brand">
): Includes the logo (logo.svg) and a list of contact information (contact-list), including email addresses and phone numbers. - Footer List (
<div class="footer-list">
): About Us section with a brief description (text) and an address (address).
Service Links and Useful Links (<ul class="footer-list">
):
- Lists of links (footer-list) related to services, useful links, and their respective titles (footer-list-title).
Subscribe Section (<div class="footer-list">
):
- Includes a title (footer-list-title), a form (footer-form) for subscribing via email (input-field and btn), and a description (text).
Footer Bottom (<div class="footer-bottom">
):
- Contains copyright information (copyright) and a list of social media links (social-list) represented by icons (logo-facebook, logo-twitter, etc.).
Back to Top Button (<a href="#top" class="back-top-btn">
):
- A button (back-top-btn) to scroll back to the top of the page, featuring an upward arrow icon (chevron-up) from Ionicons.
Scripts (<script>
):
- Includes links to external JavaScript files (script.js and Ionicons script) for functionality and icon support.
Step 2 (CSS Code):
Once the basic HTML structure of the medical website is in place, the next step is to add styling to the website using CSS. CSS allows us to control the visual appearance of the website, including things like layout, color, and typography.
Let's break down the code and its functionality:
:root Variables
:root { --rich-black-fogra-29: hsl(222, 44%, 8%); --middle-blue-green_40: hsla(174, 64%, 71%, 0.4); --midnight-green: hsl(186, 100%, 19%); --midnight-green_a25: hsla(186, 100%, 19%, 0.25); --independece: hsl(236, 14%, 39%); --verdigris: hsl(182, 100%, 35%); --ming: hsl(186, 72%, 24%); --space-cadet: hsla(226, 45%, 24%); --eerie-black: hsl(0, 0%, 13%); --alice-blue: hsl(187, 25%, 94%); --gray-web: hsl(0, 0%, 50%); --gainsboro: hsl(0, 0%, 87%); --white: hsl(0, 0%, 100%); --white_a20: hsla(0, 0%, 100%, 0.2); --white_a10: hsla(0, 0%, 100%, 0.1); --black: hsl(0, 0%, 0%); --ff-oswald: 'Oswald', sans-serif; --ff-rubik: 'Rubik', sans-serif; --headline-lg: 5rem; --headline-md: 3rem; --headline-sm: 2rem; --title-lg: 1.8rem; --title-md: 1.5rem; --title-sm: 1.4rem; --fw-500: 500; --fw-700: 700; --section-padding: 120px; --shadow-1: 0px 2px 20px hsla(209, 36%, 72%, 0.2); --shadow-2: 0 4px 16px hsla(0, 0%, 0%, 0.06); --radius-circle: 50%; --radius-12: 12px; --radius-6: 6px; --radius-4: 4px; --transition-1: 0.25s ease; --transition-2: 0.5s ease; --transition-3: 1s ease; --cubic-in: cubic-bezier(0.51, 0.03, 0.64, 0.28); --cubic-out: cubic-bezier(0.05, 0.83, 0.52, 0.97); }
- Color Variables: Defines various colors using HSL (Hue, Saturation, Lightness) and HSLA (Hue, Saturation, Lightness, Alpha) color formats.
- Font Family Variables: Specifies custom fonts 'Oswald' and 'Rubik' as fallbacks.
- Typography Variables: Sets font sizes (--headline-lg, --headline-md, etc.) and font weights (--fw-500, --fw-700).
- Spacing and Dimension Variables: Defines padding (--section-padding), box shadows (--shadow-1, --shadow-2), border radii (--radius-circle, --radius-12, etc.), transitions (--transition-1, --transition-2, --transition-3), and cubic-bezier functions (--cubic-in, --cubic-out).
General Styles
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; } li { list-style: none; } a, img, span, time, input, button, ion-icon { display: block; }
- Reset Styles: Resets margins, paddings, and sets box-sizing to border-box for all elements.
- List Styles: Removes default list styles (list-style: none; for li elements).
- Display Styles: Forces a, img, span, time, input, button, and ion-icon to be block-level elements.
Body and Typography
a { color: inherit; text-decoration: none; } img { height: auto; } input, button { background: none; border: none; font: inherit; } input { width: 100%; outline: none; } button { cursor: pointer; } ion-icon { pointer-events: none; } address { font-style: normal; } html { font-size: 10px; font-family: var(--ff-rubik); scroll-behavior: smooth; } body { background-color: var(--white); font-size: 1.6rem; color: var(--independece); line-height: 1.8; overflow: hidden; } body.loaded { overflow-y: visible; } body.nav-active { overflow: hidden; }
- Link Styles: Sets link styles to inherit color and removes underline (text-decoration: none;).
- Image Styles: Ensures images maintain aspect ratio (height: auto;).
- Form Control Styles: Removes background and border from input and button elements, and inherits font styles.
- Input Styles: Sets input width to 100% and removes outline (outline: none;).
- Button Styles: Sets cursor: pointer; for buttons.
- Icon Styles: Disables pointer events for ion-icon elements.
- Typography: Defines base font size (font-size: 1.6rem;), font family (font-family: var(--ff-rubik);), and other typographic styles.
Component Styles
.container { padding-inline: 16px; } .headline-lg { font-size: var(--headline-lg); color: var(--white); font-weight: var(--fw-500); line-height: 1.2; } .headline-md { font-size: var(--headline-md); font-weight: var(--fw-700); } .headline-lg, .headline-md { font-family: var(--ff-oswald); } .headline-md, .headline-sm { line-height: 1.3; } .headline-md, .headline-sm { color: var(--midnight-green); } .headline-sm { font-size: var(--headline-sm); } .title-lg { font-size: var(--title-lg); } .title-md { font-size: var(--title-md); } .title-sm { font-size: var(--title-sm); } .social-list { display: flex; } .section { padding-block: var(--section-padding); } .has-before, .has-after { position: relative; z-index: 1; } .has-before::before, .has-after::after { content: ""; position: absolute; }
- Container: Adds padding to .container elements (padding-inline: 16px;).
- Typography Variants: Defines styles for different headline and title sizes using the custom variables (--headline-lg, --headline-md, etc.).
- Social List: Displays .social-list items in a flex container.
- Section: Applies padding defined by --section-padding to .section elements.
- Pseudo-elements: Sets up .has-before and .has-after for use with pseudo-elements (::before and ::after), positioning them absolutely with z-index.
Button Styles
.btn { background-color: var(--verdigris); color: var(--white); font-weight: var(--fw-700); padding: 12px 36px; display: flex; align-items: center; gap: 8px; border-radius: var(--radius-6); overflow: hidden; } .btn::before { top: 0; left: -100%; width: 100%; height: 100%; background-color: var(--eerie-black); border-radius: var(--radius-6); transition: var(--transition-2); z-index: -1; } .btn:is(:hover, :focus-visible)::before { transform: translateX(100%); }
Button Styles (btn):
- Sets the background color to var(--verdigris) and text color to var(--white).
- Applies a font weight of var(--fw-700) (bold).
- Defines padding, displays as flex to align items center, sets gap between items, and rounds corners with border-radius: var(--radius-6).
- Uses overflow: hidden to hide any overflowing content.
Button Pseudo-element (::before):
- Positioned outside the button (left: -100%), covering its entire area.
- Initially colored var(--eerie-black) with the same border radius.
- Has a transition effect defined by var(--transition-2).
- Positioned behind (z-index: -1).
Button Interaction (:hover, :focus-visible):
- On hover or when focused (for accessibility), the pseudo-element moves to the right (transform: translateX(100%)), revealing it with a transition effect.
Utility Classes
.w-100 { width: 100%; } .grid-list { display: grid; gap: 40px 28px; } .text-center { text-align: center; }
- .w-100: Sets width to 100%.
- .grid-list: Sets up a grid layout with a specific gap between rows and columns.
- .text-center: Centers text horizontally within its container.
Reveal Animation
[data-reveal] { opacity: 0; transition: var(--transition-2); } [data-reveal].revealed { opacity: 1; } [data-reveal="bottom"] { transform: translateY(50px); } [data-reveal="bottom"].revealed { transform: translateY(0); } [data-reveal="left"] { transform: translateX(-50px); } [data-reveal="right"] { transform: translateX(50px); } [data-reveal="left"].revealed, [data-reveal="right"].revealed { transform: translateX(0); }
Data Reveal Animations:
- Applies opacity transition (var(--transition-2)) to elements with [data-reveal].
- Elements with class .revealed become visible (opacity: 1).
- Specific animations for reveal directions (bottom, left, right) using transforms.
Preloader Styles
.preloader { position: fixed; top: 0; left: 0; width: 100%; height: 100vh; background-color: var(--verdigris); display: grid; place-items: center; z-index: 6; transition: var(--transition-1); } .preloader.loaded { visibility: hidden; opacity: 0; } .preloader .circle { width: 50px; height: 50px; border: 4px solid var(--white); border-radius: var(--radius-circle); border-block-start-color: transparent; animation: rotate360 1s ease infinite; } @keyframes rotate360 { 0% { transform: rotate(0); } 100% { transform: rotate(1turn); } }
- Positioned fixed to cover the viewport.
- Uses var(--verdigris) background color and centers content.
- Fades out with opacity transition (var(--transition-1)) when .loaded class is added.
- Animation (rotate360) for the spinning effect of .circle element.
Header and Navbar Styles
.header .btn { display: none; } .header { position: absolute; top: 0; left: 0; width: 100%; padding-block: 16px; z-index: 4; } .header.active { position: fixed; background-color: var(--rich-black-fogra-29); animation: headerActive 0.5s ease forwards; } @keyframes headerActive { 0% { transform: translateY(-100%); } 100% { transform: translateY(0); } } .header .container { display: flex; justify-content: space-between; align-items: center; } .nav-open-btn { color: var(--white); font-size: 4rem; } .navbar, .overlay { position: fixed; top: 0; width: 100%; height: 100vh; } .navbar { right: -300px; max-width: 300px; background-color: var(--rich-black-fogra-29); z-index: 3; transition: 0.25s var(--cubic-in); visibility: hidden; } .navbar.active { transform: translateX(-300px); visibility: visible; transition: 0.5s var(--cubic-out); } .navbar-top { position: relative; padding-inline: 25px; padding-block: 55px 100px; } .nav-close-btn { position: absolute; top: 15px; right: 20px; color: var(--white); font-size: 2.8rem; } .navbar-list { margin-block-end: 30px; border-block-end: 1px solid var(--white_a10); } .navbar-item { border-block-start: 1px solid var(--white_a10); } .navbar-link { color: var(--white); text-transform: uppercase; padding: 10px 24px; }
Header (header):
- Contains a hidden .btn element.
- Initially positioned absolutely at the top of the viewport (position: absolute;).
- Uses z-index to layer elements (z-index: 4;).
Active Header (header.active):
- Positioned fixed when active, with background color var(--rich-black-fogra-29).
- Animates header appearance (animation: headerActive 0.5s ease forwards;).
Navbar (navbar):
- Positioned fixed at the top with initial right offset (right: -300px;).
- Maximum width set (max-width: 300px;).
- Uses transitions (transition: 0.25s var(--cubic-in);) and visibility control.
- Animates slide-in (transform: translateX(-300px);).
Navbar Links (navbar-link):
- Styled with uppercase text and padding.
.social-list
.social-list { justify-content: center; gap: 20px; color: var(--white); font-size: 1.8rem; }
Styles a list of social icons or links.
- justify-content: center;: Centers items horizontally within their container.
- gap: 20px;: Specifies the gap between items.
- color: var(--white);: Sets the text color to white, using a CSS variable.
- font-size: 1.8rem;: Sets the font size to 1.8 times the root font size.
.overlay
.overlay { right: -100%; background-color: var(--black); opacity: 0.3; visibility: hidden; transition: var(--transition-2); z-index: 2; } .overlay.active { transform: translateX(-100%); visibility: visible; }
Styles an overlay used for modal or background shading.
- Default state (overlay):
- right: -100%;: Initially positioned off-screen to the right.
- background-color: var(--black);: Background color set to black.
- opacity: 0.3;: Opacity set to 30%.
- visibility: hidden;: Initially hidden.
- transition: var(--transition-2);: Smooth transition as defined by a CSS variable.
- z-index: 2;: Positioned above content with z-index 2.
- Active state (overlay.active):
- transform: translateX(-100%);: Slides the overlay into view from right to left.
- visibility: visible;: Makes the overlay visible.
.hero-banner and .hero
.hero-banner { display: none; } .hero { background-color: var(--midnight-green); --section-padding: 200px; background-repeat: no-repeat; background-size: cover; }
Styles for hero sections.
- .hero-banner:
- display: none;: Hides the hero banner.
- .hero:
- background-color: var(--midnight-green);: Sets the background color using a CSS variable.
- --section-padding: 200px;: Defines a custom property for section padding.
- background-repeat: no-repeat;: Background image does not repeat.
- background-size: cover;: Background image covers the entire element.
.hero-subtitle and .hero-title
.hero-subtitle { color: var(--white); font-weight: var(--fw-500); padding-inline-start: 80px; } .hero-subtitle::before { top: 50%; left: 0; width: 60px; height: 1px; background-color: var(--white); } .hero-title { margin-block: 20px 30px; }
Styles for hero subtitle and title.
- .hero-subtitle:
- color: var(--white);: Sets text color to white.
- font-weight: var(--fw-500);: Sets font weight to 500 using a CSS variable.
- padding-inline-start: 80px;: Adds left padding.
- .hero-subtitle::before:
- Creates a pseudo-element before .hero-subtitle.
- Horizontal line (width: 60px; height: 1px;) styled with white color.
- .hero-title:
- margin-block: 20px 30px;: Adds margin above and below.
.hero-card
.hero-card { background-color: var(--white); border-radius: var(--radius-12); padding: 20px; }
Styles for a card within the hero section.
- background-color: var(--white);: Sets background color to white using a CSS variable.
- border-radius: var(--radius-12);: Rounds corners with a radius defined by a CSS variable.
- padding: 20px;: Adds internal spacing.
- .hero-card .card-text, .hero-card .input-wrapper, .hero-card .input-field, .hero-card .btn
- These classes define styles for text, input fields, and buttons within .hero-card. The specific styles include colors, borders, padding, and positioning as per the design requirements.
.service-list
.service-list { padding-block: 60px 30px; padding-inline: 25px; display: grid; gap: 30px; border-radius: var(--radius-12); margin-block-start: -60px; background-color: var(--white); box-shadow: var(--shadow-1); }
Styles for a list of services.
- padding-block: 60px 30px;: Vertical padding of 60px, horizontal padding of 30px.
- padding-inline: 25px;: Sets horizontal padding.
- display: grid;: Uses grid layout.
- gap: 30px;: Defines gap between grid items.
- border-radius: var(--radius-12);: Rounds corners using a CSS variable.
- margin-block-start: -60px;: Negative margin to overlap with the previous section.
- background-color: var(--white);: Sets background color to white.
- box-shadow: var(--shadow-1);: Applies a box shadow using a CSS variable.
.about
.about { padding-block-end: 0; } .about .container { display: grid; gap: 20px; } .about .section-text { margin-block: 20px 35px; }
Styles for the About section.
- .about:
- padding-block-end: 0;: Removes bottom padding.
- .about .container:
- display: grid;: Uses grid layout.
- gap: 20px;: Defines gap between grid items.
- .about .section-text:
- margin-block: 20px 35px;: Adds margin above and below the text.
.tab-list
.tab-list { display: flex; flex-wrap: wrap; gap: 20px 15px; }
Styles for a list of tabs.
display: flex;
: Displays items in a flex container.flex-wrap: wrap;
: Allows items to wrap onto multiple lines if needed.gap: 20px 15px;
: Defines the gap between items (20px vertically, 15px horizontally).
.tab-btn
.tab-btn { background-color: var(--alice-blue); color: var(--midnight-green); padding: 7px 30px; border-radius: var(--radius-6); font-weight: var(--fw-700); } .tab-btn.active { background-color: var(--verdigris); color: var(--white); }
Styles for tab buttons, including an active state.
Default state (.tab-btn):
background-color: var(--alice-blue);
: Background color using a CSS variable.color: var(--midnight-green);
: Text color using a CSS variable.padding: 7px 30px;
: Padding around the text.border-radius: var(--radius-6);
: Rounded corners using a CSS variable.font-weight: var(--fw-700);
: Font weight using a CSS variable.
Active state (.tab-btn.active):
- Changes background color and text color to highlight the active tab.
.tab-text
.tab-text { color: var(--midnight-green); margin-block: 35px; }
Styles for text associated with tabs.
color: var(--midnight-green);
: Sets text color using a CSS variable.margin-block: 35px;
: Adds vertical margin around the text.
.about-item
.about-item { display: flex; align-items: center; gap: 10px; margin-block-end: 10px; } .about-item ion-icon { color: var(--verdigris); font-size: 2rem; flex-shrink: 0; }
Styles for items within the About section.
.about-item
:display: flex;
: Displays items in a flex container.align-items: center;
: Centers items vertically.gap: 10px;
: Defines the gap between items.margin-block-end: 10px;
: Adds bottom margin.
.about-item ion-icon
:- Styles for icons within .about-item.
color: var(--verdigris);
: Sets icon color using a CSS variable.font-size: 2rem;
: Sets icon size.flex-shrink: 0;
: Prevents icon from shrinking.
.listing
.listing { background-color: var(--alice-blue); }
Styles for a listing section.
background-color: var(--alice-blue);
: Sets background color using a CSS variable.
.listing-card
.listing-card { padding: 25px 16px; display: flex; gap: 20px; border: 2px solid var(--middle-blue-green_40); border-radius: var(--radius-12); transition: var(--transition-1); } .listing-card:is(:hover, :focus-visible) { border-color: var(--verdigris); }
Styles for cards within a listing section.
.listing-card
:padding: 25px 16px;
: Sets padding inside the card.display: flex;
: Displays items in a flex container.gap: 20px;
: Defines the gap between items.border: 2px solid var(--middle-blue-green_40);
: Sets border color using a CSS variable.border-radius: var(--radius-12);
: Rounds corners using a CSS variable.transition: var(--transition-1);
: Defines a transition effect using a CSS variable.
.listing-card:is(:hover, :focus-visible)
:- Changes the border color on hover or focus using a CSS selector and a CSS variable.
.blog
.blog { background-image: linear-gradient(to bottom, var(--alice-blue) 60%, var(--white) 60%); padding-block-start: 0; }
Styles for a blog section.
background-image: linear-gradient(to bottom, var(--alice-blue) 60%, var(--white) 60%);
:- Sets a gradient background using a CSS linear gradient.
- Fades from var(--alice-blue) at the top to var(--white) at 60% down.
padding-block-start: 0;
: Removes top padding.
.blog-card
.blog-card { padding: 50px 36px; border-radius: var(--radius-12); border: 2px solid var(--alice-blue); background-image: url('https://raw.githubusercontent.com/farazc60/Project-Images/main/medical/assets/blog-card.jpg'); background-repeat: no-repeat; background-position: center; background-size: cover; overflow: hidden; } .blog-card::before, .blog-card::after { inset: 0; z-index: -1; transition: var(--transition-3); } .blog-card::before { background-color: var(--midnight-green); opacity: 0.9; } .blog-card::after { background-color: var(--white); } .blog-card:is(:hover, :focus-within)::after { transform: translateY(100%); }
Styles for cards within the blog section.
.blog-card
:padding: 50px 36px;
: Sets padding inside the card.border-radius: var(--radius-12);
: Rounds corners using a CSS variable.border: 2px solid var(--alice-blue);
: Sets border color using a CSS variable.background-image: url(...);
: Sets background image from a URL.background-repeat: no-repeat;
: Background image does not repeat.background-position: center;
: Centers the background image.background-size: cover;
: Scales the background image to cover the entire element.overflow: hidden;
: Hides any overflow content.
.blog-card::before and .blog-card::after
:- Pseudo-elements styled for background effects with transitions using CSS variables.
.blog-card:is(:hover, :focus-within)::after
:- Transforms the pseudo-element on hover or focus within.
.footer
.footer { background-color: var(--midnight-green); color: var(--white); background-size: contain; background-position: top right; background-repeat: no-repeat; }
Styles for the footer section.
background-color: var(--midnight-green);
: Sets the background color using a CSS variable.color: var(--white);
: Sets the text color using a CSS variable.background-size: contain;
: Ensures the background image size is contained within its area.background-position: top right;
: Positions the background image at the top right.background-repeat: no-repeat;
: Prevents the background image from repeating.
.footer-top
.footer-top { display: grid; gap: 40px; padding-block-end: 60px; }
Styles for the top section of the footer.
display: grid;
: Displays items in a grid layout.gap: 40px;
: Defines the gap between grid items.padding-block-end: 60px;
: Adds bottom padding to the top section of the footer.
.footer-brand
.footer-brand { background-color: var(--ming); padding: 32px; border-radius: var(--radius-6); }
Styles for the brand section within the footer.
background-color: var(--ming);
: Sets the background color using a CSS variable.padding: 32px;
: Adds padding inside the element.border-radius: var(--radius-6);
: Rounds corners using a CSS variable.
.contact-item
.contact-item { display: flex; align-items: flex-start; gap: 12px; margin-block-start: 12px; }
Styles for contact items within the footer.
display: flex;
: Displays items in a flex container.align-items: flex-start;
: Aligns items to the start of the cross axis.gap: 12px;
: Defines the gap between items.margin-block-start: 12px;
: Adds top margin to each contact item.
.contact-link
.contact-link, .footer-link { display: inline; transition: var(--transition-1); } .contact-link:is(:hover, :focus-visible), .footer-link:is(:hover, :focus-visible) { color: var(--verdigris); }
Styles for contact and footer links.
.contact-link and .footer-link
:display: inline;
: Displays links inline.transition: var(--transition-1);
: Applies a transition effect using a CSS variable.:is(:hover, :focus-visible)
: Selects links on hover or when focused.- Changes text color to var(--verdigris) (a shade of green) on hover or focus.
.footer-form
.footer-form .input-field { color: var(--white); border: 1px solid var(--white_a20); border-radius: var(--radius-4); padding: 8px 20px; } .footer-form .input-field::placeholder { color: inherit; } .footer-form .btn { width: 100%; justify-content: center; margin-block: 12px 28px; }
Styles for the form within the footer.
.footer-form .input-field
:color: var(--white);
: Sets text color using a CSS variable.border: 1px solid var(--white_a20);
: Sets border color using a CSS variable.border-radius: var(--radius-4);
: Rounds corners using a CSS variable.padding: 8px 20px;
: Adds padding inside the input field.
.footer-form .input-field::placeholder
:color: inherit;
: Inherits text color from its parent.
.footer-form .btn
:width: 100%;
: Sets button width to full width.justify-content: center;
: Centers button content horizontally.margin-block: 12px 28px;
: Adds margin around the button.
.footer-bottom
.footer-bottom { padding-block: 32px; border-block-start: 1px solid var(--white_a20); }
Styles for the bottom section of the footer.
padding-block: 32px;
: Adds padding inside the bottom section.border-block-start: 1px solid var(--white_a20);
: Adds a top border using a CSS variable.
.back-top-btn
.back-top-btn { position: fixed; bottom: 30px; right: 30px; background-color: var(--verdigris); color: var(--white); padding: 16px; font-size: 2rem; border-radius: var(--radius-circle); transition: var(--transition-1); opacity: 0; z-index: 3; } .back-top-btn:is(:hover, :focus-visible) { background-color: var(--eerie-black); } .back-top-btn.active { transform: translateY(-10px); opacity: 1; }
Styles for the back-to-top button.
position: fixed;
: Fixes the button's position on the viewport.bottom: 30px; right: 30px;
: Positions the button near the bottom right corner.background-color: var(--verdigris);
: Sets background color using a CSS variable.color: var(--white);
: Sets text color using a CSS variable.padding: 16px;
: Adds padding inside the button.font-size: 2rem;
: Sets font size.border-radius: var(--radius-circle);
: Rounds corners using a CSS variable.transition: var(--transition-1);
: Applies a transition effect using a CSS variable.opacity: 0;
: Initially hides the button.z-index: 3;
: Sets the stacking order of the button.:is(:hover, :focus-visible)
: Selects the button on hover or focus.- Changes background color on hover or focus.
.back-top-btn.active
: Applies styles when the button has the active class.transform: translateY(-10px);
: Moves the button up slightly.opacity: 1;
: Makes the button visible.
@media (min-width: 768px)
@media (min-width: 768px) { :root { --headline-lg: 8rem; --headline-md: 4.8rem; } .container { max-width: 750px; width: 100%; margin-inline: auto; } .header .btn { display: block; } .nav-open-btn { margin-inline-start: auto; } .header .container { gap: 40px; } .hero-title { line-height: 1.125; } .hero .wrapper { display: flex; gap: 16px; } .hero-card .input-wrapper { flex-grow: 1; } .hero-card .input-field { height: 100%; } .hero-card .btn { width: max-content; margin-block-start: 0; } .service-list { grid-template-columns: 1fr 1fr; } .about-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); } .about-banner { max-width: max-content; margin-inline: auto; } .listing .grid-list { grid-template-columns: 1fr 1fr; } .listing .grid-list > li:first-child { grid-column: 1 / 3; } .footer-top { grid-template-columns: 1fr 1fr; } .footer-brand { grid-column: 1 / 3; } .contact-list { display: flex; flex-wrap: wrap; align-items: center; gap: 24px; } .footer-bottom { display: flex; justify-content: space-between; align-items: center; } .footer-bottom .social-list { margin-block-start: 0; } }
Variables (:root)
: Sets variables for large and medium headline sizes..container
: Limits maximum width and centers content..header .btn
: Displays buttons in the header..nav-open-btn
: Adjusts margin for navigation open button..header .container
: Increases gap between items in the header..hero-title
: Adjusts line height for hero section titles..hero .wrapper
: Arranges items in the hero section horizontally..hero-card .input-wrapper
: Expands input wrapper to fill available space..hero-card .input-field
: Sets input field height to 100%..hero-card .btn
: Adjusts button width and removes top margin..service-list
: Arranges service list items in two columns..about-list
: Organizes about section items into a flexible grid..about-banner
: Centers the about section banner horizontally..listing .grid-list
: Divides listing items into two columns..footer-top
: Organizes footer top section into two columns..footer-brand
: Spans footer brand across both columns..contact-list
: Aligns contact items in a flexible row with gaps..footer-bottom
: Distributes items evenly in the footer bottom section..footer-bottom .social-list
: Removes a top margin from social links.
@media (min-width: 992px)
@media (min-width: 992px) { .container { max-width: 940px; } .hero-banner { display: block; max-width: max-content; } .hero .container { display: grid; grid-template-columns: 1fr 1fr; align-items: center; } .service-list { grid-template-columns: repeat(4, 1fr); } .about .container { grid-template-columns: 1fr 0.8fr; align-items: flex-end; } .about-content { padding-block-end: var(--section-padding); } .about-banner { margin-inline-end: -80px; } .blog .grid-list { grid-template-columns: 1fr 1fr; } }
.container
: Adjusts maximum width for larger screens..hero-banner
: Displays the hero banner image and centers it..hero .container
: Organizes hero section content into two columns..service-list
: Arranges service list items into four columns..about .container
: Positions about section items into two columns with alignment..about-content
: Adds padding to the bottom of the about section..about-banner
: Adjusts margin to the right for the about banner..blog .grid-list
: Divides blog listing items into two columns.
@media (min-width: 1200px)
@media (min-width: 1200px) { .container { max-width: 1200px; } .header { padding-block: 24px; } .nav-open-btn, .overlay, .navbar-top, .navbar .social-list { display: none; } .navbar, .navbar.active, .navbar-list { all: unset; display: block; } .navbar { margin-inline-start: auto; } .navbar-list { display: flex; gap: 8px; } .navbar-item { border-block-start: none; } .navbar-link { --title-md: 1.8rem; font-weight: var(--fw-500); padding-inline: 16px; text-transform: capitalize; } .hero .container { grid-template-columns: 0.8fr 1fr; gap: 96px; } .listing .grid-list { grid-template-columns: repeat(4, 1fr); } .blog .grid-list { grid-template-columns: repeat(3, 1fr); } .footer { background-size: auto; } .footer-top { grid-template-columns: repeat(4, 1fr); } .footer-brand { grid-column: 1 / 5; padding: 28px 56px; display: grid; grid-template-columns: 0.3fr 1fr; align-items: center; } .footer .logo { margin-block-end: 0; } .contact-list { justify-content: space-between; } .contact-list::after { top: 0; left: 50%; width: 2px; height: 100%; background-color: var(--white_a20); } .contact-item { margin-block-start: 0; } }
.container
: Adjusts maximum width for very large screens..header
: Adds padding to the header section..nav-open-btn, .overlay, .navbar-top, .navbar .social-list
: Hides navigation elements and social links..navbar, .navbar.active, .navbar-list
: Displays the navigation bar..navbar
: Aligns the navigation bar to the right..navbar-list
: Arranges navigation items in a row with gaps..navbar-item
: Removes top border from navigation items..navbar-link
: Sets font weight and padding for navigation links..hero .container
: Organizes hero section content into two columns with increased gap..listing .grid-list
: Divides listing items into four columns..blog .grid-list
: Divides blog listing items into three columns..footer
: Adjusts background size for the footer..footer-top
: Organizes footer top section into four columns..footer-brand
: Spans footer brand across all columns with specific padding and alignment..contact-list
: Distributes contact items evenly across the footer..contact-list::after
: Adds a vertical separator in the contact list..contact-item
: Removes top margin from contact items.
:root {
--rich-black-fogra-29: hsl(222, 44%, 8%);
--middle-blue-green_40: hsla(174, 64%, 71%, 0.4);
--midnight-green: hsl(186, 100%, 19%);
--midnight-green_a25: hsla(186, 100%, 19%, 0.25);
--independece: hsl(236, 14%, 39%);
--verdigris: hsl(182, 100%, 35%);
--ming: hsl(186, 72%, 24%);
--space-cadet: hsla(226, 45%, 24%);
--eerie-black: hsl(0, 0%, 13%);
--alice-blue: hsl(187, 25%, 94%);
--gray-web: hsl(0, 0%, 50%);
--gainsboro: hsl(0, 0%, 87%);
--white: hsl(0, 0%, 100%);
--white_a20: hsla(0, 0%, 100%, 0.2);
--white_a10: hsla(0, 0%, 100%, 0.1);
--black: hsl(0, 0%, 0%);
--ff-oswald: 'Oswald', sans-serif;
--ff-rubik: 'Rubik', sans-serif;
--headline-lg: 5rem;
--headline-md: 3rem;
--headline-sm: 2rem;
--title-lg: 1.8rem;
--title-md: 1.5rem;
--title-sm: 1.4rem;
--fw-500: 500;
--fw-700: 700;
--section-padding: 120px;
--shadow-1: 0px 2px 20px hsla(209, 36%, 72%, 0.2);
--shadow-2: 0 4px 16px hsla(0, 0%, 0%, 0.06);
--radius-circle: 50%;
--radius-12: 12px;
--radius-6: 6px;
--radius-4: 4px;
--transition-1: 0.25s ease;
--transition-2: 0.5s ease;
--transition-3: 1s ease;
--cubic-in: cubic-bezier(0.51, 0.03, 0.64, 0.28);
--cubic-out: cubic-bezier(0.05, 0.83, 0.52, 0.97);
}
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
li { list-style: none; }
a,
img,
span,
time,
input,
button,
ion-icon { display: block; }
a {
color: inherit;
text-decoration: none;
}
img { height: auto; }
input,
button {
background: none;
border: none;
font: inherit;
}
input {
width: 100%;
outline: none;
}
button { cursor: pointer; }
ion-icon { pointer-events: none; }
address { font-style: normal; }
html {
font-size: 10px;
font-family: var(--ff-rubik);
scroll-behavior: smooth;
}
body {
background-color: var(--white);
font-size: 1.6rem;
color: var(--independece);
line-height: 1.8;
overflow: hidden;
}
body.loaded { overflow-y: visible; }
body.nav-active { overflow: hidden; }
.container { padding-inline: 16px; }
.headline-lg {
font-size: var(--headline-lg);
color: var(--white);
font-weight: var(--fw-500);
line-height: 1.2;
}
.headline-md {
font-size: var(--headline-md);
font-weight: var(--fw-700);
}
.headline-lg,
.headline-md { font-family: var(--ff-oswald); }
.headline-md,
.headline-sm { line-height: 1.3; }
.headline-md,
.headline-sm { color: var(--midnight-green); }
.headline-sm { font-size: var(--headline-sm); }
.title-lg { font-size: var(--title-lg); }
.title-md { font-size: var(--title-md); }
.title-sm { font-size: var(--title-sm); }
.social-list { display: flex; }
.section { padding-block: var(--section-padding); }
.has-before,
.has-after {
position: relative;
z-index: 1;
}
.has-before::before,
.has-after::after {
content: "";
position: absolute;
}
.btn {
background-color: var(--verdigris);
color: var(--white);
font-weight: var(--fw-700);
padding: 12px 36px;
display: flex;
align-items: center;
gap: 8px;
border-radius: var(--radius-6);
overflow: hidden;
}
.btn::before {
top: 0;
left: -100%;
width: 100%;
height: 100%;
background-color: var(--eerie-black);
border-radius: var(--radius-6);
transition: var(--transition-2);
z-index: -1;
}
.btn:is(:hover, :focus-visible)::before { transform: translateX(100%); }
.w-100 { width: 100%; }
.grid-list {
display: grid;
gap: 40px 28px;
}
.text-center { text-align: center; }
[data-reveal] {
opacity: 0;
transition: var(--transition-2);
}
[data-reveal].revealed { opacity: 1; }
[data-reveal="bottom"] { transform: translateY(50px); }
[data-reveal="bottom"].revealed { transform: translateY(0); }
[data-reveal="left"] { transform: translateX(-50px); }
[data-reveal="right"] { transform: translateX(50px); }
[data-reveal="left"].revealed,
[data-reveal="right"].revealed { transform: translateX(0); }
.preloader {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-color: var(--verdigris);
display: grid;
place-items: center;
z-index: 6;
transition: var(--transition-1);
}
.preloader.loaded {
visibility: hidden;
opacity: 0;
}
.preloader .circle {
width: 50px;
height: 50px;
border: 4px solid var(--white);
border-radius: var(--radius-circle);
border-block-start-color: transparent;
animation: rotate360 1s ease infinite;
}
@keyframes rotate360 {
0% { transform: rotate(0); }
100% { transform: rotate(1turn); }
}
.header .btn { display: none; }
.header {
position: absolute;
top: 0;
left: 0;
width: 100%;
padding-block: 16px;
z-index: 4;
}
.header.active {
position: fixed;
background-color: var(--rich-black-fogra-29);
animation: headerActive 0.5s ease forwards;
}
@keyframes headerActive {
0% { transform: translateY(-100%); }
100% { transform: translateY(0); }
}
.header .container {
display: flex;
justify-content: space-between;
align-items: center;
}
.nav-open-btn {
color: var(--white);
font-size: 4rem;
}
.navbar,
.overlay {
position: fixed;
top: 0;
width: 100%;
height: 100vh;
}
.navbar {
right: -300px;
max-width: 300px;
background-color: var(--rich-black-fogra-29);
z-index: 3;
transition: 0.25s var(--cubic-in);
visibility: hidden;
}
.navbar.active {
transform: translateX(-300px);
visibility: visible;
transition: 0.5s var(--cubic-out);
}
.navbar-top {
position: relative;
padding-inline: 25px;
padding-block: 55px 100px;
}
.nav-close-btn {
position: absolute;
top: 15px;
right: 20px;
color: var(--white);
font-size: 2.8rem;
}
.navbar-list {
margin-block-end: 30px;
border-block-end: 1px solid var(--white_a10);
}
.navbar-item { border-block-start: 1px solid var(--white_a10); }
.navbar-link {
color: var(--white);
text-transform: uppercase;
padding: 10px 24px;
}
.social-list {
justify-content: center;
gap: 20px;
color: var(--white);
font-size: 1.8rem;
}
.overlay {
right: -100%;
background-color: var(--black);
opacity: 0.3;
visibility: hidden;
transition: var(--transition-2);
z-index: 2;
}
.overlay.active {
transform: translateX(-100%);
visibility: visible;
}
.hero-banner { display: none; }
.hero {
background-color: var(--midnight-green);
--section-padding: 200px;
background-repeat: no-repeat;
background-size: cover;
}
.hero-subtitle {
color: var(--white);
font-weight: var(--fw-500);
padding-inline-start: 80px;
}
.hero-subtitle::before {
top: 50%;
left: 0;
width: 60px;
height: 1px;
background-color: var(--white);
}
.hero-title { margin-block: 20px 30px; }
.hero-card {
background-color: var(--white);
border-radius: var(--radius-12);
padding: 20px;
}
.hero-card .card-text {
color: var(--eerie-black);
border-block-end: 1px solid var(--midnight-green_a25);
padding-block-end: 12px;
margin-block-end: 14px;
}
.hero-card .input-wrapper { position: relative; }
.hero-card .input-field {
color: var(--eerie-black);
border-block-end: 1px solid var(--gainsboro);
padding-inline-end: 18px;
}
.hero-card .input-wrapper ion-icon {
position: absolute;
top: 50%;
right: 0;
transform: translateY(-50%);
color: var(--verdigris);
}
.hero-card .btn {
width: 100%;
justify-content: center;
margin-block-start: 16px;
}
.service-list {
padding-block: 60px 30px;
padding-inline: 25px;
display: grid;
gap: 30px;
border-radius: var(--radius-12);
margin-block-start: -60px;
background-color: var(--white);
box-shadow: var(--shadow-1);
}
.service-card { text-align: center; }
.service-card .card-icon,
.btn-circle {
max-width: max-content;
margin-inline: auto;
}
.service-card .card-icon { margin-block-end: 25px; }
.service-card .card-text { margin-block: 20px 15px; }
.service-card .btn-circle {
color: var(--verdigris);
font-size: 2rem;
padding: 18px;
border-radius: var(--radius-circle);
box-shadow: var(--shadow-2);
transition: var(--transition-1);
}
.service-card .btn-circle:is(:hover, :focus-visible) {
background-color: var(--verdigris);
color: var(--white);
}
.about { padding-block-end: 0; }
.about .container {
display: grid;
gap: 20px;
}
.about .section-text { margin-block: 20px 35px; }
.tab-list {
display: flex;
flex-wrap: wrap;
gap: 20px 15px;
}
.tab-btn {
background-color: var(--alice-blue);
color: var(--midnight-green);
padding: 7px 30px;
border-radius: var(--radius-6);
font-weight: var(--fw-700);
}
.tab-btn.active {
background-color: var(--verdigris);
color: var(--white);
}
.tab-text {
color: var(--midnight-green);
margin-block: 35px;
}
.about-item {
display: flex;
align-items: center;
gap: 10px;
margin-block-end: 10px;
}
.about-item ion-icon {
color: var(--verdigris);
font-size: 2rem;
flex-shrink: 0;
}
.listing { background-color: var(--alice-blue); }
.listing-card {
padding: 25px 16px;
display: flex;
gap: 20px;
border: 2px solid var(--middle-blue-green_40);
border-radius: var(--radius-12);
transition: var(--transition-1);
}
.listing-card:is(:hover, :focus-visible) { border-color: var(--verdigris); }
.listing-card .card-title {
margin-block-end: 5px;
font-family: var(--ff-oswald);
}
.listing-card .card-text { color: var(--midnight-green); }
.blog {
background-image: linear-gradient(to bottom, var(--alice-blue) 60%, var(--white) 60%);
padding-block-start: 0;
}
.blog .section-title { margin-block-end: 60px; }
.blog-card {
padding: 50px 36px;
border-radius: var(--radius-12);
border: 2px solid var(--alice-blue);
background-image: url('https://raw.githubusercontent.com/farazc60/Project-Images/main/medical/assets/blog-card.jpg');
background-repeat: no-repeat;
background-position: center;
background-size: cover;
overflow: hidden;
}
.blog-card::before,
.blog-card::after {
inset: 0;
z-index: -1;
transition: var(--transition-3);
}
.blog-card::before {
background-color: var(--midnight-green);
opacity: 0.9;
}
.blog-card::after { background-color: var(--white); }
.blog-card:is(:hover, :focus-within)::after { transform: translateY(100%); }
.blog-card .meta-wrapper {
display: flex;
flex-wrap: wrap;
gap: 5px 20px;
margin-block-end: 12px;
}
.blog-card .card-meta {
display: flex;
align-items: center;
gap: 5px;
color: var(--midnight-green);
}
.blog-card .card-meta ion-icon { font-size: 1.8rem; }
.blog-card .card-meta:first-child .span { text-transform: uppercase; }
.blog-card .date {
color: var(--space-cadet);
font-weight: var(--fw-700);
text-transform: uppercase;
opacity: 0.5;
margin-block: 16px;
}
.blog-card .btn-text {
color: var(--verdigris);
margin-block-start: 12px;
}
.blog-card :is(.card-meta, .card-title, .date, .card-text, .btn-text) {
transition: var(--transition-2);
}
.blog-card:is(:hover, :focus-within) :is(.card-meta, .card-title, .date, .card-text, .btn-text) {
color: var(--white);
}
.footer {
background-color: var(--midnight-green);
color: var(--white);
background-size: contain;
background-position: top right;
background-repeat: no-repeat;
}
.footer-top {
display: grid;
gap: 40px;
padding-block-end: 60px;
}
.footer-brand {
background-color: var(--ming);
padding: 32px;
border-radius: var(--radius-6);
}
.footer .logo { margin-block-end: 20px; }
.contact-item {
display: flex;
align-items: flex-start;
gap: 12px;
margin-block-start: 12px;
}
.contact-item .item-icon { font-size: 4rem; }
.contact-link {
display: inline;
transition: var(--transition-1);
}
.contact-link:is(:hover, :focus-visible) { color: var(--verdigris); }
.footer-list-title {
color: var(--white);
font-weight: var(--fw-700);
margin-block-end: 20px;
}
.footer .text { opacity: 0.7; }
.footer .address {
display: flex;
align-items: center;
gap: 12px;
margin-block-start: 20px;
}
.footer .address ion-icon {
font-size: 4rem;
flex-shrink: 0;
}
.footer-link {
margin-block-start: 8px;
transition: var(--transition-1);
}
.footer-link:is(:hover, :focus-visible) { color: var(--verdigris); }
.footer-form .input-field {
color: var(--white);
border: 1px solid var(--white_a20);
border-radius: var(--radius-4);
padding: 8px 20px;
}
.footer-form .input-field::placeholder { color: inherit; }
.footer-form .btn {
width: 100%;
justify-content: center;
margin-block: 12px 28px;
}
.footer-bottom {
padding-block: 32px;
border-block-start: 1px solid var(--white_a20);
}
.footer-bottom .social-list {
justify-content: flex-start;
gap: 8px;
margin-block-start: 16px;
}
.footer-bottom .social-link {
font-size: 1.4rem;
padding: 12px;
background-color: var(--white_a10);
border-radius: var(--radius-circle);
transition: var(--transition-1);
}
.footer-bottom .social-link:is(:hover, :focus-visible) { background-color: var(--verdigris); }
.back-top-btn {
position: fixed;
bottom: 30px;
right: 30px;
background-color: var(--verdigris);
color: var(--white);
padding: 16px;
font-size: 2rem;
border-radius: var(--radius-circle);
transition: var(--transition-1);
opacity: 0;
z-index: 3;
}
.back-top-btn:is(:hover, :focus-visible) { background-color: var(--eerie-black); }
.back-top-btn.active {
transform: translateY(-10px);
opacity: 1;
}
@media (min-width: 768px) {
:root {
--headline-lg: 8rem;
--headline-md: 4.8rem;
}
.container {
max-width: 750px;
width: 100%;
margin-inline: auto;
}
.header .btn { display: block; }
.nav-open-btn { margin-inline-start: auto; }
.header .container { gap: 40px; }
.hero-title { line-height: 1.125; }
.hero .wrapper {
display: flex;
gap: 16px;
}
.hero-card .input-wrapper { flex-grow: 1; }
.hero-card .input-field { height: 100%; }
.hero-card .btn {
width: max-content;
margin-block-start: 0;
}
.service-list { grid-template-columns: 1fr 1fr; }
.about-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
.about-banner {
max-width: max-content;
margin-inline: auto;
}
.listing .grid-list { grid-template-columns: 1fr 1fr; }
.listing .grid-list > li:first-child { grid-column: 1 / 3; }
.footer-top { grid-template-columns: 1fr 1fr; }
.footer-brand { grid-column: 1 / 3; }
.contact-list {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 24px;
}
.footer-bottom {
display: flex;
justify-content: space-between;
align-items: center;
}
.footer-bottom .social-list { margin-block-start: 0; }
}
@media (min-width: 992px) {
.container { max-width: 940px; }
.hero-banner {
display: block;
max-width: max-content;
}
.hero .container {
display: grid;
grid-template-columns: 1fr 1fr;
align-items: center;
}
.service-list { grid-template-columns: repeat(4, 1fr); }
.about .container {
grid-template-columns: 1fr 0.8fr;
align-items: flex-end;
}
.about-content { padding-block-end: var(--section-padding); }
.about-banner { margin-inline-end: -80px; }
.blog .grid-list { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 1200px) {
.container { max-width: 1200px; }
.header { padding-block: 24px; }
.nav-open-btn,
.overlay,
.navbar-top,
.navbar .social-list { display: none; }
.navbar,
.navbar.active,
.navbar-list {
all: unset;
display: block;
}
.navbar { margin-inline-start: auto; }
.navbar-list {
display: flex;
gap: 8px;
}
.navbar-item { border-block-start: none; }
.navbar-link {
--title-md: 1.8rem;
font-weight: var(--fw-500);
padding-inline: 16px;
text-transform: capitalize;
}
.hero .container {
grid-template-columns: 0.8fr 1fr;
gap: 96px;
}
.listing .grid-list { grid-template-columns: repeat(4, 1fr); }
.blog .grid-list { grid-template-columns: repeat(3, 1fr); }
.footer { background-size: auto; }
.footer-top { grid-template-columns: repeat(4, 1fr); }
.footer-brand {
grid-column: 1 / 5;
padding: 28px 56px;
display: grid;
grid-template-columns: 0.3fr 1fr;
align-items: center;
}
.footer .logo { margin-block-end: 0; }
.contact-list { justify-content: space-between; }
.contact-list::after {
top: 0;
left: 50%;
width: 2px;
height: 100%;
background-color: var(--white_a20);
}
.contact-item { margin-block-start: 0; }
}
Step 3 (JavaScript Code):
To enhance user experience, add interactive features with JavaScript. Here's a detailed explanation of each part of the code:
'use strict'; Directive
'use strict';
- This line enforces strict mode, which helps catch common coding errors and improves performance.
Function to Add Event Listeners
const addEventOnElements = function (elements, eventType, callback) { for (let i = 0, len = elements.length; i < len; i++) { elements[i].addEventListener(eventType, callback); } }
- This function, addEventOnElements, takes an array of elements, an event type (like 'click'), and a callback function. It adds the specified event listener to each element in the array.
Preloader
const preloader = document.querySelector("[data-preloader]"); window.addEventListener("load", function () { preloader.classList.add("loaded"); document.body.classList.add("loaded"); });
- This code selects an element with the attribute data-preloader. When the window fully loads, it adds the class loaded to the preloader and the body, likely used to hide the preloader and signify that the page has fully loaded.
Navbar Toggler
const navbar = document.querySelector("[data-navbar]"); const navTogglers = document.querySelectorAll("[data-nav-toggler]"); const overlay = document.querySelector("[data-overlay]"); const toggleNav = function () { navbar.classList.toggle("active"); overlay.classList.toggle("active"); document.body.classList.toggle("nav-active"); } addEventOnElements(navTogglers, "click", toggleNav);
- This section handles the navigation bar toggling. It selects elements for the navbar, togglers, and overlay. The toggleNav function toggles the active class on the navbar and overlay, and the nav-active class on the body. This function is added as a click event listener to all nav togglers using the addEventOnElements function.
Header and Back-to-Top Button Activation on Scroll
const header = document.querySelector("[data-header]"); const backTopBtn = document.querySelector("[data-back-top-btn]"); const activeElementOnScroll = function () { if (window.scrollY > 100) { header.classList.add("active"); backTopBtn.classList.add("active"); } else { header.classList.remove("active"); backTopBtn.classList.remove("active"); } } window.addEventListener("scroll", activeElementOnScroll);
- This code selects the header and back-to-top button elements. The activeElementOnScroll function checks if the window's scroll position is greater than 100 pixels. If it is, it adds the active class to the header and back-to-top button, otherwise, it removes the class. This function is attached to the window's scroll event.
Reveal Elements on Scroll
const revealElements = document.querySelectorAll("[data-reveal]"); const revealElementOnScroll = function () { for (let i = 0, len = revealElements.length; i < len; i++) { if (revealElements[i].getBoundingClientRect().top < window.innerHeight / 1.15) { revealElements[i].classList.add("revealed"); } else { revealElements[i].classList.remove("revealed"); } } } window.addEventListener("scroll", revealElementOnScroll); window.addEventListener("load", revealElementOnScroll);
- This part targets all elements with the attribute data-reveal. The revealElementOnScroll function checks if the top of each reveal element is within a certain portion of the viewport height (less than window.innerHeight / 1.15). If true, it adds the revealed class; otherwise, it removes it. This function is added to both the scroll and load events to handle the revealing of elements on page load and during scrolling.
'use strict';
const addEventOnElements = function (elements, eventType, callback) {
for (let i = 0, len = elements.length; i < len; i++) {
elements[i].addEventListener(eventType, callback);
}
}
const preloader = document.querySelector("[data-preloader]");
window.addEventListener("load", function () {
preloader.classList.add("loaded");
document.body.classList.add("loaded");
});
const navbar = document.querySelector("[data-navbar]");
const navTogglers = document.querySelectorAll("[data-nav-toggler]");
const overlay = document.querySelector("[data-overlay]");
const toggleNav = function () {
navbar.classList.toggle("active");
overlay.classList.toggle("active");
document.body.classList.toggle("nav-active");
}
addEventOnElements(navTogglers, "click", toggleNav);
const header = document.querySelector("[data-header]");
const backTopBtn = document.querySelector("[data-back-top-btn]");
const activeElementOnScroll = function () {
if (window.scrollY > 100) {
header.classList.add("active");
backTopBtn.classList.add("active");
} else {
header.classList.remove("active");
backTopBtn.classList.remove("active");
}
}
window.addEventListener("scroll", activeElementOnScroll);
const revealElements = document.querySelectorAll("[data-reveal]");
const revealElementOnScroll = function () {
for (let i = 0, len = revealElements.length; i < len; i++) {
if (revealElements[i].getBoundingClientRect().top < window.innerHeight / 1.15) {
revealElements[i].classList.add("revealed");
} else {
revealElements[i].classList.remove("revealed");
}
}
}
window.addEventListener("scroll", revealElementOnScroll);
window.addEventListener("load", revealElementOnScroll);
Final Output:
Conclusion:
Building a responsive medical landing page using HTML, CSS, and JavaScript requires careful planning and attention to detail. By following the steps outlined in this guide, you can create a professional, user-friendly website that meets the needs of your patients. Remember to focus on responsiveness, usability, and accessibility to ensure your site stands out in the competitive medical field. A well-designed website not only enhances your online presence but also helps build trust and credibility with your audience.
Design and Code by: Sadee
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!
Thanks!
Faraz 😊