How to Create a TikTok Clone Using HTML, CSS, and JavaScript (Source Code)

Faraz

By Faraz -

Learn how to create a TikTok clone from scratch with this detailed tutorial using HTML, CSS, and JavaScript. Source code included!


How to Create a TikTok Clone Using HTML, CSS, and JavaScript.webp

Table of Contents

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

In today's digital age, social media platforms like TikTok have revolutionized the way we consume and interact with content. With its short video format and engaging features, TikTok has captured the attention of millions worldwide. If you've ever wondered how such platforms are built, you're in the right place.

In this tutorial, we'll delve into the fascinating world of web development by creating our own TikTok clone from scratch.

Whether you're a seasoned developer looking to expand your skill set or a curious beginner eager to dive into web development, this guide is tailored for you. By the end of this journey, you'll not only have a better understanding of web development principles but also a fully functional TikTok clone to showcase your newfound skills.

So, let's embark on this exciting journey of creativity, innovation, and learning as we bring our TikTok clone to life. Let's get started!

Source Code

Step 1 (HTML Code):

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

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

Here's a breakdown of what each part does:

1. <!DOCTYPE html>: This declaration specifies the document type and version of HTML used, which in this case is HTML5.

2. <html lang="en">: This tag indicates the beginning of the HTML document, with the specified language set to English (en).

3. <head>: This section contains metadata about the document, such as character encoding, viewport settings, and the page title.

  • <meta charset="UTF-8">: Sets the character encoding to UTF-8, which supports most characters from different languages.
  • <meta http-equiv="X-UA-Compatible" content="IE=edge">: Specifies the version of Internet Explorer to use to render the page.
  • <meta name="viewport" content="width=device-width, initial-scale=1.0">: Sets the viewport width to the device's width and initial zoom level to 1.
  • <title>Tik Tok Clone</title>: Sets the title of the webpage to "Tik Tok Clone".

4. External CSS are linked:

  • <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">: Links the Font Awesome stylesheet, which provides icons used in the webpage.
  • <link rel="stylesheet" href="styles.css">: Links an external CSS file named "styles.css" for additional styling.

5. <body>: This section contains the content of the webpage visible to the user.

  • <div class="container">: Wraps all content within a container.
  • Inside the container, there's a <div class="video-container"> which holds the TikTok-like video player and other elements.
  • The video player (<video>) displays a video with autoplay and loop attributes.
  • Various icons and buttons (<i> tags with Font Awesome classes) for actions like following, liking, commenting, and sharing the video.
  • Comments section with input field and send button.
  • A Post footer containing username, description, and music name.
  • A disc logo image at the bottom.

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

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

Step 2 (CSS Code):

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

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

Here's a breakdown of what each part does:

1. Core Styling:

  • The first part sets some base styles for all elements, removing default padding and margins, and ensuring that the box-sizing property is set to "border-box" (which includes padding and border in the element's total width and height).
  • It also hides the scrollbar in Webkit-based browsers.

2. Body Styling:

  • Sets a linear gradient background for the body, which animates over 15 seconds, creating a shifting color effect.
  • It centers the content both horizontally and vertically using the grid layout.
  • Sets the default font size, text color, and cursor style for the body.

3. Link Styling:

  • Removes the default underline from links and sets their color and cursor style.

4. Main Styling:

  • Styles a container element to be centered both horizontally and vertically and to occupy the entire viewport.
  • Styles a video container, including its size, border radius, box shadow, and scroll behavior.
  • Defines styles for a video container header, including its position, size, and alignment of its content.
  • Sets styles for individual posts, including their size and overflow behavior.
  • Defines styles for a video player, including its position and size, with a shadow effect.
  • Styles a sidebar, setting its position, size, and alignment.
  • Defines styles for post footers, including their position, size, and text color.
  • Styles elements related to user profiles, such as usernames and verification icons.
  • Defines styles for a disc logo, including its position, size, and animation.
  • Sets styles for elements within the sidebar, such as follow buttons and profile images.
  • Defines styles for side icons, such as their size, padding, and color.

5. Post Comments:

  • Styles a section for comments, setting its position, size, background color, and transition effect.
  • Defines styles for comment elements, including their position, size, and alignment.
  • Sets styles for comment input elements, including text fields and send buttons.
  • Styles-specific elements related to music names and song titles.
  • Defines styles for video elements within posts, ensuring they fill the container and maintain aspect ratio.

6. Keyframes:

  • Defines two animation keyframes: one for animating the gradient background and another for animating a rotating disc logo.

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

/* core styling */
*,
*:before,
*:after {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  outline: none;
}
*::-webkit-scrollbar {
  display: none;
  height: 0;
  width: 0;
}

body {
  background-size: 400% 400%;
  display: grid;
  place-items: center;
  font-size: 20px;
  color: #000;
  cursor: pointer;
  animation: gradient 15s ease infinite;
}

a {
  text-decoration: none;
  color: #333;
  cursor: pointer;
}

/* main styling */
.container {
  display: grid;
  place-items: center;
  height: 100vh;
  width: 100vw;
}

.video-container {
  position: relative;
  border-radius: 10px;
  height: 659px;
  width: 330px;
  box-shadow: 0 0 50px #000;
  margin: auto;
  overflow: scroll;
  scroll-snap-type: y mandatory;
  scroll-snap-align: center;
}
/* video container header */
.video-container-header {
  position: absolute;
  top: 20px;
  left: 0;
  width: 100%;
  height: 50px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  text-align: center;
  z-index: 3;
}
.video-container-header div {
  width: 100%;
  height: 100%;
  display: flex;
  font-size: 15px;
  color: #ccc;
  justify-content: center;
  align-items: center;
  cursor: pointer;
}
.video-container-header div.active {
  font-size: 20px;
  color: #fff;
}
.post {
  position: relative;
  height: 659px;
  width: 330px;
  overflow: hidden;
  scroll-snap-align: center;
}
.video-player {
  position: relative;
  height: 100%;
  width: 100%;
}
.video-player::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  height: 100%;
  width: 100%;
  box-shadow: inset 0 0 120px #000;
}
.side-bar {
  position: absolute;
  right: 0;
  top: 50%;
  z-index: 2;
  transform: translate(0, -50%);
}
.post-footer {
  position: absolute;
  width: 80%;
  bottom: 0;
  left: 0;
  padding: 10px;
  color: #fff;
  z-index: 2;
}
.post-footer a {
  color: #fff;
}
.post-footer .username {
  display: flex;
  height: 30px;
  align-items: center;
}
.post-footer .username .username-link::before {
  content: '@ ';
  color: #fff;
}
.verfied .verfied-icon,
.post-comment-user-verified {
  height: 20px;
  width: 20px;
  margin-left: 10px;
  font-size: 9px;
  border-radius: 50%;
  background-color: #008abf;
  display: grid;
  place-items: center;
}
.post-description {
  padding-left: 10px;
  font-size: 10px;
}
.disc-logo {
  position: absolute;
  right: 10px;
  bottom: 10px;
  height: 50px;
  width: 50px;
  border-radius: 50%;
  overflow: hidden;
  z-index: 2;
  animation: disc-anime infinite linear 2s;
}
.disc-logo-img {
  height: 100%;
  width: 100%;
  object-fit: cover;
  transform: scale(1.4);
}
.side-bar .profile-follow {
  position: relative;
}
.side-bar .profile-follow .fa-plus {
  font-size: 10px;
  position: absolute;
  top: 65%;
  left: 50%;
  transform: translate(-50%);
  height: 20px;
  width: 20px;
  border-radius: 50%;
  background-color: #ff2828;
  display: flex;
  justify-content: center;
  align-items: center;
}
.side-bar .profile-logo-img {
  overflow: hidden;
  height: 40px;
  width: 40px;
  border-radius: 50%;
}
.side-bar .side-icon {
  cursor: pointer;
  padding: 20px;
  font-size: 25px;
  text-align: center;
  color: #fff;
}
.side-icon p {
  font-size: 10px;
  padding-top: 5px;
}
/* post comments */
.post-comments {
  position: absolute;
  bottom: -100%;
  left: 0;
  height: 50%;
  width: 100%;
  border-radius: 10px 10px 0 0;
  padding: 10px;
  background-color: #fff;
  z-index: 5;
  transition: all 0.5s ease;
}
.post-comments::before {
  content: '';
  position: absolute;
  top: 5px;
  left: 50%;
  width: 50%;
  padding: 1px;
  background-color: #333;
  border-radius: 50px;
  transform: translate(-50%);
}
.post-comments.open {
  bottom: 0;
}
.close-comment {
  position: absolute;
  top: 10px;
  right: 10px;
  cursor: pointer;
  font-size: 20px;
  font-weight: 300px;
}
.post-comments-area {
  height: 250px;
  overflow: scroll;
  margin-top: 20px;
}
.post-comment {
  margin: 10px auto;
  display: flex;
  width: 100%;
  height: 50px;
  align-items: center;
  justify-content: space-between;
  text-align: left;
}
.post-comment-user-name {
  display: flex;
}
.post-comment-user-img {
  overflow: hidden;
  border-radius: 50%;
  height: 40px;
  width: 40px;
}
.post-comment-user-verified {
  width: 15px;
  height: 15px;
  font-size: 10px;
}
.post-comment-user-msg {
  font-size: 14px;
}
.post-comment-like-btn {
  text-align: center;
  cursor: pointer;
}
.post-comment-like-btn p {
  font-size: 10px;
}
.post-comment-like-btn .post-comment-like-icon.liked {
  color: #ff2828;
}
.post-comment-content {
  display: flex;
  flex-direction: column;
  padding-left: 20px;
  justify-content: center;
  width: 100%;
}
.post-comment-input {
  display: flex;
  height: 50px;
  width: 100%;
  align-items: center;
  justify-content: flex-start;
}
.post-comment-text {
  height: 40px;
  width: 100%;
  border: 0;
  padding: 10px 20px;
}
.post-comment-send {
  height: 40px;
  width: 40px;
  border: 0;
  background-color: transparent;
  cursor: pointer;
}
.music-name {
  display: flex;
  font-size: 10px;
  padding: 5px;
}
.song-name {
  margin-left: 10px;
}
video.post-video {
  height: 100%;
  width: 100%;
  object-fit: cover;
}

@keyframes gradient {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}

@keyframes disc-anime {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
} 

Step 3 (JavaScript Code):

Finally, we need to create a function in JavaScript.

Here's a breakdown of what each section does:

1. Video Player Controls:

  • It sets up event listeners for video player elements.
  • When a video player is clicked, it either plays or pauses the corresponding video.

2. Disc Icon Addition:

  • It creates a disc icon element and appends it to each post element.

3. Like Button Functionality:

  • It sets up event listeners for like buttons.
  • When a like button is clicked, it toggles between liking and unliking a post, updating the like count accordingly.

4. Post Comment Box:

  • It handles the opening and closing of the comment section for each post.

5. Adding Comments to Posts:

  • It handles adding comments to posts.
  • It sets up event listeners to send comments.
  • When the send button is clicked, it creates a new comment element with the user's comment and appends it to the corresponding post's comment area.

6. Post Comment Like Functionality:

  • It sets up event listeners for liking comments.
  • When a comment's like button is clicked, it toggles between liking and unliking the comment, updating the like count accordingly.

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

const postVideo = document.querySelectorAll(".post-video");
const videoPlayer = document.querySelectorAll(".video-player");
const post = document.querySelectorAll(".post");
let isPlaying = true;

postVideo.forEach((item, index) => {
  item.loop = true;
  item.autoBuffer = true;
  videoPlayer[index].addEventListener("click", function () {
    isPlaying ? pauseVideo(index) : playVideo(index);
  });
});

function playVideo(index) {
  postVideo[index].play();
  isPlaying = true;
}

function pauseVideo(index) {
  postVideo[index].pause();
  isPlaying = false;
}

// disc icon
const discSrc =
  "data:image/png;base64,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";
const discContainer = document.createElement("div");
const discImg = document.createElement("img");
discContainer.setAttribute("class", "disc-logo");
discImg.src = discSrc;
discImg.setAttribute("class", "disc-logo-img");
discContainer.appendChild(discImg);
post.forEach((item, index) => {
  post[index].appendChild(discContainer);
});

// like button
const likeBtn = document.querySelectorAll(".like-btn");
const likeBtnIcon = document.querySelectorAll(".like-icon");
const likeBtnNum = document.querySelectorAll(".like-number");
let isLiked = false;

likeBtn.forEach((item, index) => {
  likeBtn[index].addEventListener("click", function () {
    //changing like Number
    let likeNum = Math.floor(likeBtnNum[index].innerText);
    // change like button
    isLiked ? unLikePost(index, likeNum) : likePost(index, likeNum);
  });
});

function likePost(index, likeNum) {
  isLiked = true;
  likeBtnIcon[index].classList.replace("fa-heart-o", "fa-heart");
  likeBtnNum[index].innerText = likeNum + 1;
}

function unLikePost(index, likeNum) {
  isLiked = false;
  likeBtnIcon[index].classList.replace("fa-heart", "fa-heart-o");
  likeBtnNum[index].innerText = likeNum - 1;
}

// post comment box
const postComments = document.querySelectorAll(".post-comments");
const commentBtn = document.querySelectorAll(".comment-btn");
const commentClose = document.querySelectorAll(".close-comment");

postComments.forEach((item, index) => {
  commentBtn[index].addEventListener("click", function () {
    postComments[index].classList.add("open");
  });

  commentClose[index].addEventListener("click", function () {
    postComments[index].classList.remove("open");
  });
});

//add coments to post

const postCommentSendBtn = document.querySelectorAll(".send-btn");
const postCommentText = document.querySelectorAll(".post-comment-text");
const postCommentArea = document.querySelectorAll(".post-comments-area");

postCommentSendBtn.forEach((item, index) => {
  if (postCommentText[index].value == "") {
    window.addEventListener("keydown", (evnt) => {
      if (evnt.keyCode == 13) submitComment();
    });
  }
  postCommentSendBtn[index].addEventListener("click", function () {
    if (postCommentText[index].value != "") {
      const postComment = document.createElement("div");
      const postCommentUser = document.createElement("div");
      const postCommentContent = document.createElement("div");
      const postCommentLikeBtn = document.createElement("div");

      // postCommentUser
      //adding class to postCommentUser
      postCommentUser.setAttribute("class", "post-comment-user");
      postCommentUser.classList.add("verified");
      //creating child elements to postCommentUser
      const postCommentUserImg = document.createElement("img");
      postCommentUserImg.setAttribute("class", "post-comment-user-img");
      postCommentUserImg.setAttribute(
        "src",
        "http://dankmemeryt.000webhostapp.com/wp-content/uploads/2020/12/logo.webp"
      );
      //appending to postCommentUser
      postCommentUser.appendChild(postCommentUserImg);

      //postCommentContent
      // adding class to postCommentContent
      postCommentContent.setAttribute("class", "post-comment-content");
      //creating child elements to postCommentContent
      const postCommentUserName = document.createElement("div");
      const postCommentUserMsg = document.createElement("div");
      postCommentUserName.setAttribute("class", "post-comment-user-name");
      postCommentUserName.classList.add("verified");
      postCommentUserName.innerHTML = "<a href='#'>theviralboy.ig</a>";
      if (postCommentUserName == "verified") {
        const postCommentUserVerifiedIcon = document.createElement(i);
        postCommentUserVerifiedIcon.setAttribute(
          "class",
          "fa fa-check post-comment-user-verified"
        );

        postCommentUserName.appendChild(postCommentUserVerifiedIcon);
      }
      postCommentUserMsg.setAttribute("class", "post-comment-user-msg");
      postCommentUserMsg.innerText = postCommentText[index].value;

      //appending to postCommentContent
      postCommentContent.appendChild(postCommentUserName);
      postCommentContent.appendChild(postCommentUserMsg);

      //postCommentLikeBtn
      postCommentLikeBtn.setAttribute("class", "post-comment-like-btn");

      const postCommentLikeBtnIcon = document.createElement("i");
      postCommentLikeBtnIcon.setAttribute(
        "class",
        "fa fa-heart-o post-comment-like-icon"
      );
      const postCommentLikeNum = document.createElement("p");
      postCommentLikeNum.setAttribute("class", "post-comment-like-number");
      postCommentLikeNum.innerText = 9;

      //appending elements to postCommentLikeBtn
      postCommentLikeBtn.appendChild(postCommentLikeBtnIcon);
      postCommentLikeBtn.appendChild(postCommentLikeNum);

      postComment.setAttribute("class", "post-comment");

      postComment.appendChild(postCommentUser);
      postComment.appendChild(postCommentContent);
      postComment.appendChild(postCommentLikeBtn);
      //appending comment into post comment
      postCommentArea[index].appendChild(postComment);

      //blanking out postCommentText
      postCommentText[index].value = "";
    }
  });
});

// post comments like
const postCommentLikeBtn = document.querySelectorAll(".post-comment-like-btn");
const postCommentLikeIcon = document.querySelectorAll(
  ".post-comment-like-icon"
);
const postCommentLikeNum = document.querySelectorAll(
  ".post-comment-like-number"
);
let isPostCommentLiked = false;

postCommentLikeBtn.forEach((item, index) => {
  postCommentLikeBtn[index].addEventListener("click", function () {
    let num = Math.floor(postCommentLikeNum[index].innerText);
    isPostCommentLiked
      ? unLikePostComment(index, num)
      : likePostComment(index, num);
  });
});

function likePostComment(index, num) {
  isPostCommentLiked = true;
  num += 1;
  postCommentLikeIcon[index].classList.replace("fa-heart-o", "fa-heart");
  postCommentLikeIcon[index].classList.add("liked");
  postCommentLikeNum[index].innerText = num;
}

function unLikePostComment(index, num) {
  isPostCommentLiked = false;
  num -= 1;
  postCommentLikeIcon[index].classList.replace("fa-heart", "fa-heart-o");
  postCommentLikeIcon[index].classList.remove("liked");
  postCommentLikeNum[index].innerText = num;
}

Final Output:

How to Create a TikTok Clone Using HTML, CSS, and JavaScript.gif

Conclusion:

Congratulations on completing your TikTok clone using HTML, CSS, and JavaScript! Throughout this tutorial, you've learned valuable skills in web development and gained insights into replicating the functionalities of a popular social media platform.

Keep exploring, keep learning, and keep building. The possibilities in the world of web development are endless, and your journey has just begun.

Thank you for joining us on this adventure. We hope you've enjoyed creating your TikTok clone as much as we've enjoyed guiding you through the process.

Until next time, happy coding!

Code by: Sahil Verma

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