Create a URL Shortening Landing Page using HTML, CSS, and JavaScript

Faraz

By Faraz -

Learn how to create a URL shortening landing page using HTML, CSS, and JavaScript. Follow this tutorial for a user-friendly URL shortener


Create a URL Shortening Landing Page using HTML CSS JavaScript.webp

Table of Contents

  1. Project Introduction
  2. HTML Code
  3. CSS Code
  4. JavaScript Code
  5. Preview
  6. Conclusion

A URL shortening landing page is a web application that converts long URLs into shorter, more manageable links. It offers convenience and simplicity for users who need to share or remember lengthy URLs.

In this guide, we'll walk you through the process of creating your own URL shortening landing page using HTML, CSS, and JavaScript. From setting up the basic structure to adding styling and functionality, you'll learn everything you need to know to build a user-friendly and efficient URL shortener. Let's get started!

Source Code

Step 1 (HTML Code):

Setting Up HTML Structure

  • Create a new HTML file.
  • Define the basic structure with <html>, <head>, and <body> tags.
  • Set up input fields for users to enter long URLs and a button for submitting.

Here's a breakdown of the code:

1. <!DOCTYPE html>: Declares the document type and version of HTML being used.

2. <html lang="en">: Defines the beginning of the HTML document and specifies the language as English.

3. <head>: Contains meta-information about the HTML document, such as character encoding, viewport settings, and the title of the page.

  • <meta charset="UTF-8">: Sets the character encoding of the document to UTF-8.
  • <meta http-equiv="X-UA-Compatible" content="IE=edge">: Specifies the version of Internet Explorer to use.
  • <meta name="viewport" content="width=device-width, initial-scale=1.0">: Sets the viewport properties for responsive design.
  • <title>URL shortening API landing Page</title>: Sets the title of the webpage.
  • <link rel="stylesheet" href="https://site-a...css"/>: Links to an external CSS stylesheet (Font Awesome) for icons.
  • <link rel="stylesheet" href="styles.css">: Links to an external CSS file named "styles.css".

4. <body>: Contains the content of the webpage visible to users.

  • <main class="main">: Defines the main content area of the webpage.
  • <header class="header">: Represents the header section of the webpage, containing a logo, navigation menu, and a burger menu icon for mobile view.
  • <section class="landing">: Represents the landing section with a heading, a paragraph, and a call-to-action button.
  • <section class="features" id="features">: Represents the features section, including a form for shortening URLs and information about advanced statistics.
  • <section class="pricing" id="pricing">: Represents the pricing section with a heading and a call-to-action button.
  • <footer class="footer" id="resources">: Represents the footer section with links to various resources, social media icons, and attribution.

5. <script src="script.js"></script>: Links to an external JavaScript file named "script.js" for scripting functionalities.

Step 2 (CSS Code):

Styling with CSS

  • Link your CSS file to the HTML document using <link> tag.
  • Apply styles to input fields, button, and overall layout for a visually appealing design.
  • Ensure responsiveness for various screen sizes using media queries.

Let's break down the code section by section:

1. Font Import:

  • The code imports the "Poppins" font family from Google Fonts with three different weights (400, 500, and 700) and specifies to display it using the "swap" strategy.

2. Global Reset:

  • The universal selector (*) sets padding and margin to 0 and ensures box-sizing is set to "border-box" for all elements. This is a common technique to reset default browser styles.

3. General Styles:

  • Defines scroll behavior for the HTML element to be smooth.
  • Sets the default font size for the HTML element to 16 pixels.
  • Sets default styles for the body such as font-family, font-weight, and removing outline on focus.

4. Heading and Paragraph Styles:

  • Sets styles for headings (h1, h2, h3, h4) and paragraphs (p), including color, font-weight, and line-height.

5. Link Styles:

  • Removes underlines from the anchor (a) elements.

6. Image Styles:

  • Ensures images don't exceed their parent container's width.

7. Button Styles:

  • Defines styles for buttons with the class "btn", including colors, background, text-transform, font-weight, border, and border-radius.
  • Provides additional styles for buttons with classes "btn-sm" and "btn-lg" to adjust padding.
  • Defines styles for buttons with the class "btn-plus-icon" to display an icon alongside text.

8. Utility Classes:

  • Defines utility classes like ".flex-between", ".flex-ver-top", and ".scale-effect:active" for flexbox alignment, scaling effect, etc.

9. Section Header Styles:

  • Styles section headers, adjusting font size based on the viewport width.

10. Container Styles:

  • Styles a container element to have a relative position, specific width, and centered margin.

11. Header Styles:

  • Styles header elements including padding, logo size, and navigation layout for different screen sizes.

12. Landing Section Styles:

  • Styles for a landing section, including alignment, padding, and margin based on screen size.

13. URL Shorten Form Styles:

  • Styles for a form used for URL shortening, including input field styling, placeholders, and alert messages.

14. URL Shorten Results Styles:

  • Styles for displaying URL shortening results, including individual result items and associated actions.

15. More Features Section Styles:

  • Styles for a section showcasing additional features, including grid layout and illustrations.

16. Pricing Section Styles:

  • Styles for a pricing section, including background images and container alignment.

17. Footer Styles:

  • Styles for the footer section, including layout, logo, quick links, and social media icons.

18. Attribution Styles:

  • Styles for the attribution section, including text alignment and link styles.
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;700&display=swap");
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  font-size: 16px;
}

body {
  font-family: "Poppins", sans-serif, "Segoe UI", Tahoma, Geneva, Verdana;
  font-weight: 500;
  outline: none;
}

h1,
h2,
h3,
h4 {
  color: #35323e;
  font-weight: 700;
}

p {
  color: #9e9aa7;
  font-weight: 500;
  line-height: 1.7;
}

a {
  text-decoration: none;
}

img {
  max-width: 100%;
}

.btn {
  display: inline-block;
  color: white;
  background-color: #2acfcf;
  text-transform: capitalize;
  font-weight: 700;
  border: none;
  outline: none;
  cursor: pointer;
  border-radius: 100px;
  transition: 0.3s;
}

.btn.btn-sm {
  padding: 7px 21px;
}

.btn.btn-lg {
  padding: 12px 36px;
}

.btn.btn-plus-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  column-gap: 10px;
}

.btn.btn-plus-icon .icon {
  font-size: 22px;
}

.btn:hover {
  background-color: #6be1e1;
}

.flex-between {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 40px;
}

.flex-ver-top {
  align-items: flex-start;
}

.scale-effect:active {
  transform: scale(0.88);
  transition: 0.2s;
}

.section-header {
  text-align: center;
}

.section-header h2 {
  font-size: 35px;
}

@media (max-width: 500px) {
  .section-header h2 {
    font-size: 26px;
  }
}

@media (max-width: 280px) {
  .section-header h2 {
    font-size: 22px;
  }
}

.section-header p {
  width: 50%;
  margin: 7px auto 0;
}

@media (max-width: 992px) {
  .section-header p {
    width: 70%;
  }
}

@media (max-width: 500px) {
  .section-header p {
    width: 100%;
  }
}

.container {
  position: relative;
  width: 78%;
  margin: 0 auto;
}

@media (max-width: 992px) {
  .container {
    width: 90%;
  }
}

.header {
  padding: 45px 0;
}

.header .logo img {
  height: 30px;
}

.header .main-navgation {
  flex: 1;
  gap: 0;
}

@media (max-width: 992px) {
  .header .main-navgation {
    position: absolute;
    top: 150%;
    left: 50%;
    transform: translateX(-50%);
    width: 70%;
    height: 0;
    z-index: 999;
    overflow: hidden;
    flex-direction: column;
    align-items: center;
    padding: 0 33.33333px;
    border-radius: 10px;
    background-color: #3b3054;
    transition: height 0.3s;
  }
}

@media (max-width: 767px) {
  .header .main-navgation {
    width: 90%;
  }
}

@media (max-width: 375px) {
  .header .main-navgation {
    width: 100%;
  }
}

@media (max-width: 280px) {
  .header .main-navgation {
    padding: 0 25px;
  }
}

.header .main-navgation > div {
  display: flex;
  align-items: center;
  gap: 30px;
}

@media (max-width: 992px) {
  .header .main-navgation > div {
    flex-direction: column;
    width: 100%;
    padding: 33.33333px 0;
  }
}

@media (max-width: 280px) {
  .header .main-navgation > div {
    padding: 25px 0;
  }
}

.header .main-navgation div:first-child {
  border-bottom: 1px solid white;
}

.header .nav-buttons .btn {
  color: #fff;
  width: 80%;
}

@media (max-width: 375px) {
  .header .nav-buttons .btn {
    width: 100%;
  }
}

.header .burger-menu {
  font-size: 22px;
  color: #9e9aa7;
  cursor: pointer;
  display: none;
}

@media (max-width: 992px) {
  .header .burger-menu {
    display: block;
  }
}

.main-navgation a {
  font-weight: 700;
  font-size: 14px;
  color: #9e9aa7;
  transition: 0.3s;
}

.main-navgation a:hover {
  color: #232127;
}

@media (max-width: 992px) {
  .main-navgation a {
    width: 100%;
    color: white;
    text-align: center;
    font-size: 16px;
  }
  .main-navgation a:hover {
    color: #2acfcf;
  }
}

.landing {
  display: flex;
  align-items: center;
  padding: 40px 0;
  margin-left: 11%;
  overflow-x: hidden;
}

@media (max-width: 992px) {
  .landing {
    flex-direction: column-reverse;
    margin-left: 0;
    padding-bottom: 80px;
    row-gap: 60px;
  }
}

@media (max-width: 280px) {
  .landing {
    padding-bottom: 40px;
  }
}

.landing .landing-text {
  flex: 1;
  min-width: 465px;
}

@media (max-width: 992px) {
  .landing .landing-text {
    max-width: 95%;
    min-width: 0;
    text-align: center;
  }
}

.landing .landing-text h1 {
  width: 100%;
  font-size: 3.9em;
  line-height: 1.15;
}

@media (max-width: 992px) {
  .landing .landing-text h1 {
    font-size: 3em;
  }
}

@media (max-width: 500px) {
  .landing .landing-text h1 {
    font-size: 2em;
  }
}

.landing .landing-text p {
  font-size: 18px;
  max-width: 500px;
  margin: 0 0 29.41176px;
}

@media (max-width: 992px) {
  .landing .landing-text p {
    font-size: 16px;
    margin: 10px auto 29.41176px;
  }
}

@media (max-width: 500px) {
  .landing .landing-text p {
    font-size: 15px;
  }
}

.landing .landing-image {
  position: relative;
  right: -70px;
}

@media (max-width: 992px) {
  .landing .landing-image {
    flex-basis: initial;
    right: -240px;
  }
}

@media (max-width: 767px) {
  .landing .landing-image {
    right: -170px;
  }
}

@media (max-width: 500px) {
  .landing .landing-image {
    right: -110px;
  }
}

@media (max-width: 375px) {
  .landing .landing-image {
    right: -120px;
  }
}

@media (max-width: 280px) {
  .landing .landing-image {
    right: -70px;
  }
}

@media (min-width: 1100px) {
  .landing .landing-image {
    right: -130px;
  }
}

.landing .landing-image img {
  width: 100%;
}

.features {
  margin-top: 100px;
  background-color: #eff0f5;
}

.url-shorten-form {
  width: 100%;
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
  background: #3b3054 url(../images/bg-shorten-desktop.svg) no-repeat right top;
  background-size: cover;
  padding: 45px;
  border-radius: 6px;
  margin-bottom: 20px;
  transform: translateY(-50%);
  transition: gap 0.3s;
}

@media (max-width: 850px) {
  .url-shorten-form {
    flex-direction: column;
    background: #3b3054 url(../images/bg-shorten-mobile.svg) no-repeat right top;
    padding: 25px;
    margin-bottom: 0;
  }
}

@media (max-width: 280px) {
  .url-shorten-form {
    padding: 20px;
  }
}

.url-shorten-form > div {
  position: relative;
  flex: 1;
}

.url-shorten-form .url-input {
  width: 100%;
  font-family: "Poppins", sans-serif, "Segoe UI", Tahoma, Geneva, Verdana;
  font-size: 18px;
  padding: 8px 20px;
  background: white;
  border: 2px solid transparent;
  border-radius: 6px;
  outline: none;
  transition: 0.2s;
}

.url-shorten-form .url-input::placeholder {
  font-family: "Poppins", sans-serif, "Segoe UI", Tahoma, Geneva, Verdana;
  font-size: 16px;
  font-weight: 500;
  color: #9e9aa7;
}

.url-shorten-form .alert {
  position: absolute;
  left: 0;
  top: calc(100% + 4px);
  font-style: italic;
  font-size: 16px;
  color: #f46262;
  opacity: 0;
  transition: 0.2s opacity;
}

@media (max-width: 500px) {
  .url-shorten-form .alert {
    font-size: 14px;
  }
}

.url-shorten-form .btn {
  text-align: center;
  border-radius: inherit;
  white-space: nowrap;
  font-size: 16px;
  cursor: pointer;
}

@media (max-width: 850px) {
  .url-shorten-form .btn {
    font-size: 19px;
    padding: 10px 30px;
  }
}

.url-shorten-form.empty {
  gap: 37px;
}

.url-shorten-form.empty .url-input {
  border-color: #f46262;
}

.url-shorten-form.empty .url-input::placeholder {
  color: #f46262;
  opacity: 0.5;
}

.url-shorten-form.empty .alert {
  opacity: 1;
}

.url-shorten-form.success button {
  background: #30c59b;
}

.url-shorten-results {
  position: relative;
  top: -60px;
}

.url-shorten-results .url-shorten-result {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 15px;
  flex-wrap: wrap;
  padding: 15px 25px;
  background: white;
  border-radius: 6px;
  margin-bottom: 15.15152px;
}

.url-shorten-results .url-shorten-result > div p {
  font-size: 17px;
  word-break: break-word;
}

.url-shorten-results .url-shorten-result > div a:hover {
  text-decoration: underline wavy #30c59b 2px;
}

@media (max-width: 850px) {
  .url-shorten-results .url-shorten-result {
    flex-direction: column;
    align-items: flex-start;
    padding: 0;
    gap: 0;
  }
  .url-shorten-results .url-shorten-result > div {
    width: 100%;
    align-items: flex-start;
    padding: 12px 18px;
  }
}

.url-shorten-results .delete-all-urls {
  display: block;
  margin: auto;
  font-size: 15px;
  background-color: #f24a4a;
}

.url-shorten-results .delete-all-urls:hover {
  background-color: #f46262;
}

.url-shorten-result .old-url p {
  color: #35323e;
  font-weight: 500;
}

.url-shorten-result .old-url a {
  color: inherit;
}

@media (max-width: 850px) {
  .url-shorten-result .old-url {
    border-bottom: 1px solid #bfbfbf;
  }
}

.url-shorten-result .new-url {
  display: flex;
  align-items: center;
  gap: 20px;
}

.url-shorten-result .new-url a {
  color: #2acfcf;
}

@media (max-width: 850px) {
  .url-shorten-result .new-url {
    flex-direction: column;
    gap: 12px;
  }
}

.url-shorten-result .options {
  display: flex;
  gap: 10px;
}

@media (max-width: 850px) {
  .url-shorten-result .options {
    width: 100%;
  }
}

.url-shorten-result .options button {
  width: 95px;
  font-size: 15px;
  border-radius: 6px;
  cursor: pointer;
}

.url-shorten-result .options button.copied {
  background: #3b3054;
}

.url-shorten-result .options button.delete-url {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 35px;
  background: #f46262;
  border: none;
  color: white;
  font-size: 18px;
  transition: 0.2s;
}

.url-shorten-result .options button.delete-url:hover {
  color: #f46262;
  background-color: #eff0f5;
  font-size: 20px;
}

@media (max-width: 850px) {
  .url-shorten-result .options button {
    width: 100%;
    font-size: 18px;
    padding: 10px 30px;
  }
}

.more-features-content {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 25px;
  padding: 80px 0 90px 0;
}

@media (max-width: 666px) {
  .more-features-content {
    gap: 80px;
  }
}

@media (max-width: 280px) {
  .more-features-content {
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  }
}

.more-features-content .feature {
  position: relative;
  background: white;
  border-radius: 6px;
}

.more-features-content .feature:before,
.more-features-content .feature::after {
  position: absolute;
  content: "";
  background: #2acfcf;
}

@media (max-width: 666px) {
  .more-features-content > div:nth-child(2):before,
  .more-features-content > div:nth-child(2)::after {
    width: 6px;
    height: 80px;
    left: 50%;
    transform: translateX(-50%);
  }
  .more-features-content > div:nth-child(2):before {
    top: -80px;
  }
  .more-features-content > div:nth-child(2):after {
    bottom: -80px;
  }
}

@media (min-width: 1130px) {
  .more-features-content {
    align-items: flex-start;
  }
  .more-features-content > div:nth-child(2) {
    margin-top: 30px;
  }
  .more-features-content > div:nth-child(2):before,
  .more-features-content > div:nth-child(2)::after {
    height: 6px;
    width: 25px;
    top: 40%;
  }
  .more-features-content > div:nth-child(2):before {
    left: -25px;
  }
  .more-features-content > div:nth-child(2):after {
    right: -25px;
  }
  .more-features-content > div:nth-child(3) {
    margin-top: 60px;
  }
}

.feature .feature-illustration {
  position: absolute;
  top: -32.5px;
  left: 25px;
  display: grid;
  place-items: center;
  width: 65px;
  height: 65px;
  background: #3b3054;
  border-radius: 50%;
}

@media (max-width: 666px) {
  .feature .feature-illustration {
    left: 50%;
    transform: translateX(-50%);
    width: 80px;
    height: 80px;
  }
}

.feature .feature-illustration img {
  max-width: 50%;
}

.feature .feature-details {
  padding: 0 25px 30px;
  margin-top: 60px;
}

@media (max-width: 666px) {
  .feature .feature-details {
    text-align: center;
    margin-top: 80px;
  }
}

@media (max-width: 280px) {
  .feature .feature-details {
    padding: 0 20px 25px;
  }
}

@media (max-width: 500px) {
  .feature .feature-details h3 {
    font-size: 20px;
  }
}

@media (max-width: 280px) {
  .feature .feature-details h3 {
    font-size: 18px;
  }
}

.feature .feature-details p {
  margin-top: 10px;
  font-size: 14px;
}

.pricing {
  padding: 50px 0;
  background: #3b3054 url(../images/bg-boost-desktop.svg) no-repeat right;
  background-size: cover;
}

@media (max-width: 500px) {
  .pricing {
    padding: 90px 0;
    background-image: url(../images/bg-boost-mobile.svg);
  }
}

.pricing .container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100%;
}

.pricing h2 {
  color: white;
  margin-bottom: 20px;
}

.footer {
  padding-top: 50px;
  background: #232127;
}

.footer .container {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: 70px;
  flex-wrap: wrap;
}

@media (max-width: 705px) {
  .footer .container {
    flex-wrap: nowrap;
    flex-direction: column;
    align-items: center;
    gap: 30px;
  }
}

.footer .logo {
  flex: 1 0 auto;
}

.footer .logo img {
  filter: brightness(10);
}

.footer .quick-links {
  display: flex;
  gap: 60px;
}

@media (max-width: 705px) {
  .footer .quick-links {
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 30px;
  }
}

.footer .quick-links .links-group {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.footer .links-group span {
  color: white;
  font-weight: 700;
}

.footer .links-group > div {
  display: flex;
  flex-direction: column;
  gap: 6.66667px;
}

.footer .links-group a {
  color: #bfbfbf;
  font-size: 13px;
  transition: 0.2s color;
}

.footer .links-group a:hover {
  color: cyan;
}

.footer .social-media {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: 20px;
}

.footer .social-media img {
  max-width: 85%;
  transition: 0.2s transform;
}

.footer .social-media img:hover {
  transform: scale(1.1);
  filter: invert(0%) sepia(59%) saturate(6585%) hue-rotate(125deg)
    brightness(86%) contrast(85%);
}

.attribution {
  padding: 30px 0 25px 0;
  text-align: center;
  font-size: 13px;
  color: #fff;
}

.attribution .outer-link {
  font-size: 15px;
  color: #2acfcf;
  margin-left: 2px;
  cursor: pointer;
}

.attribution .outer-link:hover {
  text-decoration: underline wavy #2acfcf 2px;
}

.attribution .social-media {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  list-style: none;
  margin-left: 5px;
}

.attribution .social-media .icon {
  font-size: 20px;
  color: #fff;
}

.attribution .social-media .image {
  width: 23px;
}

.attribution .social-media .image:hover {
  filter: none;
  background-color: none;
} 

Step 3 (JavaScript Code):

Adding Functionality with JavaScript

  • Include your JavaScript file in the HTML document using <script> tag.
  • Write functions to handle URL shortening logic.
  • Use DOM manipulation to interact with HTML elements and display shortened URLs dynamically.

Let's break down what each part of the code does:

1. Global Variables:

  • These variables store references to various HTML elements like the form, input field, buttons, and alert messages, which will be used throughout the script.

2. Functions:

  • generatedShortUrlHtml(id, originalURL, shortUrl): This function generates the HTML structure for displaying the original URL and its shortened version. It also sets up event listeners for copy and delete functionalities.
  • insertAfter(newNode, existingNode): This function inserts a new node after an existing node in the DOM.
  • removeAllGeneratedURLs(): This function manages the display of the "delete all" button based on the number of generated URLs and handles the deletion of all generated URLs.
  • removeURL(): This function handles the removal of a single URL entry when the delete button associated with it is clicked.
  • copyURL(): This function allows users to copy the shortened URL to their clipboard when the copy button is clicked.
  • reandomIds(): This function generates random IDs for the shortened URLs.
  • makeShortURL(userUrl): This asynchronous function interacts with an API (https://api.shrtco.de/v2/) to shorten the provided URL. It handles responses, and errors, and updates the UI accordingly.

3. Event Listeners:

  • An event listener is attached to the form submission. When the form is submitted, it prevents the default form submission behavior, gets the input URL, triggers the URL shortening process, and resets the form.
  • There's also an event listener for the burger menu icon, toggling the navigation menu's visibility.

4. Alerts Function:

  • This function displays alert messages in the UI for different scenarios such as empty input, invalid URLs, or API errors.

5. Expand Navigation Function:

  • This function controls the behavior of the navigation menu, allowing it to expand and collapse when the burger menu icon is clicked. It also handles the closing of the navigation menu on window resize for screens larger than 992 pixels.
/*

  ////// NOTE ///////
  
LocalStorage Doesn't Wok On Coden Pen [Access Denied]. So When Refreshing The Browser All The Generated URLs will Be Removed.

To View The Full Functionality Of The Website, You Can Visit My Github Page

https://github.com/MohamedAridah/frontendmentor_url-shortening-api

*/

// Global Variables
let shortURLsWrapper = document.querySelector(".url-shorten-results");
let shortUrlForm = document.querySelector("#url-shorten-form");
let submitButton = shortUrlForm.querySelector("button");
let input = shortUrlForm.querySelector(".url-input");
let alertMessage = shortUrlForm.querySelector(".alert");

// Build Short URL HTML Structure
function generatedShortUrlHtml(id, originalURL, shortUrl) {
  shortURLsWrapper.insertAdjacentHTML(
    "beforeend",
    `
  <div class="url-shorten-result" id='${id}'>
    <div class="old-url">
    <p><a href="${originalURL}" target="_blank">${originalURL}</a></p>
    </div>
    <div class="new-url">
      <p><a href="${shortUrl}" target="_blank">${shortUrl}</a></p>
      <div class="options">
        <button type="button" class="copy-new-url btn btn-sm scale-effect">
          copy
        </button>

        <button type="button" class="delete-url scale-effect">
          <i class="fa-regular fa-trash-can icon"></i>
        </button>
      </div>
    </div>
  </div>`
  );
  removeURL();
  copyURL();
  removeAllGeneratedURLs();
}

// Put Delete Button At The End Of The Generated Links Function
function insertAfter(newNode, existingNode) {
  existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling);
}

// Add Remove All Generated URls
function removeAllGeneratedURLs() {
  // When There Is More Than One Generated URL & Delete Button Is Already Exists Delete It And Then Add It To The End Of The URLs List.
  if (shortURLsWrapper.querySelectorAll(".url-shorten-result").length >= 2) {
    if (shortURLsWrapper.querySelector(".delete-all-urls")) {
      shortURLsWrapper.querySelector(".delete-all-urls").remove();
    }
    // Create Delete Generated URLs Button
    let button = document.createElement("button");
    button.type = "button";
    button.classList = "btn btn-sm delete-all-urls scale-effect";
    button.textContent = "delete all";
    insertAfter(button, shortURLsWrapper.lastElementChild);
    // Delete All Genetared URLs & LocalStorage
    let deleteAll = shortURLsWrapper.querySelector(".delete-all-urls");
    deleteAll.addEventListener("click", () => {
      shortURLsWrapper.innerHTML = "";
      savedURLs = [];
      localStorage.removeItem("saved");
    });
  } else {
    if (shortURLsWrapper.querySelector(".delete-all-urls")) {
      shortURLsWrapper.querySelector(".delete-all-urls").remove();
    }
  }
}

// Remove Sindle URL
function removeURL() {
  let deleteURLButton = shortURLsWrapper.querySelectorAll(".delete-url");
  deleteURLButton.forEach((button) => {
    button.addEventListener("click", () => {
      // Get URL ID
      let linkId = button.closest(".url-shorten-result").id;
      // Remove URL From The List
      button.closest(".url-shorten-result").remove();
      // Get Index Of This URL And Remove It From Array
      const index = savedURLs.findIndex((url) => url.id == linkId);
      // Remove URL From The Array
      savedURLs.splice(index, 1);
      // Resave The Array & LocalStorage
      localStorage.setItem("saved", JSON.stringify(savedURLs));
      removeAllGeneratedURLs();
    });
  });
}

// Copy URl
function copyURL() {
  let copyButtons = shortURLsWrapper.querySelectorAll(".copy-new-url");
  copyButtons.forEach((button) => {
    button.addEventListener("click", () => {
      // Get URL Content
      let urlText = button
        .closest(".url-shorten-result")
        .querySelector(".new-url p").textContent;
      const body = document.querySelector("body");
      const area = document.createElement("textarea");
      body.appendChild(area);
      area.value = urlText;
      area.select();
      document.execCommand("copy");
      button.classList.add("copied");
      button.innerHTML = "copied!";
      setTimeout(() => {
        button.classList.remove("copied");
        button.innerHTML = "copy";
      }, 1500);
      body.removeChild(area);
    });
  });
}

// Generate Random IDs
function reandomIds() {
  let currentTime = Date.now();
  let currentTimeString = currentTime.toString(32).slice(0, 8);
  let reandomNumber = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)
    .toString()
    .slice(0, 4);
  let reabdomId = `${currentTimeString}-${reandomNumber}`;
  return reabdomId;
}

// shrtcode API
const makeShortURL = async (userUrl) => {
  let apiBaseURL = "https://api.shrtco.de/v2/";
  let shortenQuery = `shorten?url=`;
  let fetchLink = `${apiBaseURL}${shortenQuery}${userUrl}`;

  try {
    let response = await fetch(fetchLink);
    let data = await response.json();
    let status = data.ok;

    // Response With Data
    if (status) {
      let originalURL = data.result.original_link;
      let shortUrl = data.result.full_short_link;
      // Make Object For [originalURL, shortUrl]
      let generatedURL = {
        id: reandomIds(),
        originalURL: originalURL,
        shortUrl: shortUrl
      };
      // Change Submit Button Text & Style
      shortUrlForm.classList.add("success");
      submitButton.innerHTML = `<i class="fa-solid fa-check icon"></i> shortened!`;
      setTimeout(() => {
        shortUrlForm.classList.remove("success");
        submitButton.innerHTML = "shorten it!";
      }, 1700);
      generatedShortUrlHtml(reandomIds(), originalURL, shortUrl);
      // Save [link] Object To Localstorage After Pushing It To The [savedURLs] Array
      savedURLs.push(generatedURL);
      localStorage.setItem("saved", JSON.stringify(savedURLs));
    }
    // Response With Error Message [No Data].
    else {
      // Change Submit Button Text
      submitButton.innerHTML = "shorten it!";
      let errorCode = data.error_code;
      switch (errorCode) {
        // If Input Is Empty
        case 1:
          alerts("Please add a link first");
          break;
        // If URL Is Not Valid
        case 2:
          alerts(data.error.split(",")[0] + ", Please check your link again.");
          break;
        // If URL Is Not Allowed To Be Shortened
        case 10:
          alerts("The link you entered is not allowed to be shortened.");
          break;
        // Any Other Problem
        default:
          alerts(data.error);
      }
    }
  } catch (error) {
    // Incase Can't Connect To The Api [Ex: No Internet Connection]
    alerts("Sorry, unknown error happened please try again later.");
  }
};

shortUrlForm.addEventListener("submit", (e) => {
  e.preventDefault();
  // Get Input Value & Remove Extra Spaces.
  let inputValue = input.value.trim().replace(" ", "");
  // Change Submit Button Text
  submitButton.innerHTML = `<i class="fa-solid fa-spinner icon fa-spin"></i> Generating...`;
  makeShortURL(inputValue);
  // Clear Input
  shortUrlForm.reset();
});

// Show Alerts
function alerts(message) {
  shortUrlForm.classList.add("empty");
  alertMessage.textContent = message;

  setTimeout(() => {
    shortUrlForm.classList.remove("empty");
  }, 5000);
}

// Expand Header Navgation Function
function expandNavgation() {
  let navgation = document.querySelector(".header .main-navgation");
  let toggleMenu = document.querySelector(".header .burger-menu");
  let icon = toggleMenu.querySelector(".icon");
  let closed = true;

  toggleMenu.addEventListener("click", () => {
    // Change Icon
    if (icon.classList.contains("fa-bars")) {
      icon.className = "fa-regular fa-xmark icon";
    } else {
      icon.className = "fa-regular fa-bars icon";
    }

    // Open Or Close Navgation Menu
    let navgationHeight = navgation.scrollHeight;
    if (closed) {
      navgation.style.height = `${navgationHeight}px`;
    } else {
      navgation.style.height = "";
    }
    closed = !closed;
  });
  // Close Navgation For Devices Greater Than 992px Width.
  window.addEventListener("resize", () => {
    if (window.innerWidth > 992) {
      icon.className = "fa-regular fa-bars icon";
      navgation.style.height = "";
      closed = true;
    }
  });
}
expandNavgation();

Final Output:

Create a URL Shortening Landing Page using HTML CSS JavaScript.gif

Conclusion:

In conclusion, creating a URL shortening landing page using HTML, CSS, and JavaScript offers a practical and valuable tool for simplifying the sharing of long URLs. By following the steps outlined in this guide, you can develop a functional and aesthetically pleasing landing page that enhances user experience.

From setting up the HTML structure to styling with CSS and adding functionality with JavaScript, each step plays a crucial role in the development process. Additionally, testing and optimization ensure that your landing page performs optimally across various devices and browsers.

Thank you for joining us on this tutorial. We hope you found it informative and inspiring. Happy coding!

Code by: Mohamed Aridah

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 😊

End of the article

Subscribe to my Newsletter

Get the latest posts delivered right to your inbox


Latest Post