Welcome everyone to this simple and easy screen recording project that we are going to be working on together, using just plain old HTML, CSS and some JavaScript. You may wonder why someone would need something like this. The answer is that capturing screen activity is essential for tutorials, presentations, bug reporting and many more. Whether you are looking to create a step-by-step video for your channel or looking to send your impressive portfolio to a potential client, you may need something like this app. In the following post I’ll walk you through a minimal yet powerful screen recorder, built entirely with HTML, CSS, and JavaScript.
Tools
Now, like I said earlier, we will not be using any libraries, however if you have no coding experience, I highly recommend this tutorial here, on how to get started with code editors.
What are we actually going to build?
This project allows the user to record their device screen along with complete audio track directly from their preferred browser. When you press the record button, you will be prompted to select what element you like to record, such as a browser tab (Chrome in my case), if you have multiple apps or windows, it will prompt you to choose one, or you can simply choose to record the entire screen. In the bottom right corner, you also have the ‘Also share with audio’ option which you can enable or disable at your convenience. A countdown timer precedes the recording, and the final video is available to download in WebM format.
The code is lightweight, requiring no external libraries, and takes advantage of native browser APIs.
Let’s take a closer look.
Breakdown
- HTML structures the interface, including a video preview, a record button, and a download link.
- CSS styles the layout, adds responsiveness, and creates an engaging countdown overlay.
- JavaScript handles screen capture, video recording, and download logic.
Great, now let’s dive into the code and see how it works.
HTML Structure
First you will need to create an index.html file
, in which we will write, you guessed it, the HTML code that will provide the very basic UI. Again, if you have previous experience with coding, feel free to modify it to suit the needs of your own project, if you have no coding experience just go ahead copy the code below as is.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css" />
<script src="script.js" defer></script>
<title>Screen Recorder</title>
</head>
<body>
<div class="countdown" id="countdown"></div>
<div class="screen-recorder">
<h1>Capture your media screen</h1>
<video controls preload="none" id="video"></video>
<nav>
<button type="button" class="btn" id="btn" aria-label="Start recording">Record</button>
<a href="#" class="btn" id="link" aria-label="Download recorded video" download="recording.webm">Download Video</a>
</nav>
</div>
</body>
</html>
The video
element displays the recorded screen, while the button
and the a
elements allow for the recording process to begin and later for download.
CSS Styling
Next, we will be taking a look at how we can make our project more visually appealing and just like we did with the index.html file, we will also need to create a style.css. For those that are unfamiliar with CSS, you can find a great deal of free lessons here.
Now let’s take a closer look at the CSS:
-
Global Reset:
*
applies padding, margin reset, andbox-sizing: border-box
globally to ensure consistent spacing across elements. -
Body Centering: The body uses
display: grid
andplace-items: center
to center everything vertically and horizontally. -
Countdown Overlay: The
.countdown
class is hidden by default (visibility: hidden
) and appears as a Fullscreen overlay during countdown. Thefont-size: 10rem
makes the countdown digits large and visible. -
Screen Recorder Layout:
.screen-recorder
centers its content using flexbox, aligns items in a column, and adds spacing between elements with gap:2rem
. -
Responsive Video: The video element scales responsively, adjusting based on the screen size, thanks to the
width: 100%
andmax-width
constraints. -
Buttons:
.btn
provides a consistent look for buttons with a blue background, white text, and hover effect (background-color: #357ec7
). -
Responsive Design: The
@media query
ensures the layout and font sizes adapt on screens smaller than768px
, making the app mobile-friendly.
If you are unfamiliar with CSS media queries, you can find a great deal of information and free tutorials here.
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
width: 100vw;
min-height: 100vh;
display: grid;
place-items: center;
background-color: #f4f4f4;
}
.countdown {
visibility: hidden;
color: green;
font-size: 10rem;
font-weight: 900;
background-color: rgba(0, 0, 0, 0.5); /* Semi-transparent black background */
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 10000;
display: flex;
align-items: center;
justify-content: center;
}
.screen-recorder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 2rem;
width: 90%;
max-width: 1000px;
padding: 2rem;
background-color: #fff;
color: #202020;
border-radius: 10px;
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.2);
}
.screen-recorder video {
width: 100%;
max-width: 782px;
aspect-ratio: 16 / 9;
max-height: 440px;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1), -2px -2px 5px rgba(0, 0, 0, 0.1);
border-radius: 10px;
display: none;
}
h1 {
text-transform: capitalize;
font-size: 3rem;
font-weight: bold;
color: #202020;
}
.btn {
background-color: #428bca;
color: #fff;
font-weight: 900;
padding: 0.75rem 1.5rem;
border-radius: 0.5rem;
cursor: pointer;
text-transform: capitalize;
border: 1px solid #428bca;
transition: background-color 0.3s ease, color 0.3s ease;
}
.btn:hover,
.btn:focus {
background-color: #357ec7;
outline: 2px solid #357ec7;
outline-offset: 2px;
}
a {
text-decoration: none;
margin-inline-start: 20px;
display: none;
}
@media (max-width: 768px) {
.screen-recorder video {
width: 100%;
height: auto;
}
h1 {
font-size: 2.5rem;
}
.btn {
padding: 0.5rem 1rem;
font-size: 1rem;
}
.countdown {
font-size: 6rem;
}
}
All of the above code ensures a minimal and user-friendly interface, again for those of you that are more experienced, feel free to modify the code as you see fit.
JavaScript Functionality
In the previous chapters we’ve looked at the HTML and CSS code, now it’s time to take a closer look at the brain of our app, the JavaScript code.
As before, you will need to create a script.js
file in which our main JavaScript logic will reside. Again, if you are new to this, just copy and paste the below code into your script.js file.
const startBtn = document.getElementById("btn");
const downloadLink = document.getElementById("link");
const videoElement = document.getElementById("video");
const countdownElement = document.getElementById("countdown");
let blob = null,
videoStream = null,
audioStream = null;
startBtn.addEventListener("click", startScreenCapturing);
async function startScreenCapturing() {
if (!navigator.mediaDevices.getDisplayMedia) {
alert("Screen capturing is not supported in your browser.");
return;
}
if (videoStream) {
videoStream.getTracks().forEach(track => track.stop());
}
if (audioStream) {
audioStream.getTracks().forEach(track => track.stop());
}
try {
videoStream = await navigator.mediaDevices.getDisplayMedia({
video: true,
audio: true,
});
try {
audioStream = await navigator.mediaDevices.getUserMedia({
audio: {
echoCancellation: true,
noiseSuppression: true,
sampleRate: 44100,
},
});
const audioTrack = audioStream.getTracks()[0];
videoStream.addTrack(audioTrack);
} catch (error) {
console.warn("No audio stream available:", error);
}
startBtn.textContent = "Recording...";
startBtn.disabled = true;
await recordStream(videoStream);
} catch (error) {
console.error("Screen capture failed:", error);
startBtn.textContent = "Record";
startBtn.disabled = false;
}
}
function countdown(seconds = 3) {
return new Promise((resolve) => {
let counter = seconds;
countdownElement.style.visibility = "visible";
countdownElement.textContent = counter;
const interval = setInterval(() => {
counter--;
countdownElement.textContent = counter;
if (counter < 0) {
clearInterval(interval);
countdownElement.style.visibility = "hidden";
resolve();
}
}, 1000);
});
}
function showRecordedVideo() {
if (!blob) {
console.error("No recorded video available.");
return;
}
if (videoElement.src) {
URL.revokeObjectURL(videoElement.src);
}
videoElement.src = URL.createObjectURL(blob);
videoElement.style.display = "block";
downloadLink.href = videoElement.src;
downloadLink.download = "screen-recording.webm";
downloadLink.style.display = "inline-block";
startBtn.textContent = "Record";
startBtn.disabled = false;
}
async function recordStream(stream) {
await countdown();
const supportedMimeType = MediaRecorder.isTypeSupported("video/webm; codecs=vp8,opus")
? "video/webm; codecs=vp8,opus"
: "video/webm";
const mediaRecorder = new MediaRecorder(stream, {
mimeType: supportedMimeType,
});
const recordedChunks = [];
mediaRecorder.addEventListener("dataavailable", (e) => recordedChunks.push(e.data));
const videoTrack = stream.getVideoTracks()[0];
if (videoTrack) {
videoTrack.addEventListener("ended", () => mediaRecorder.stop());
}
mediaRecorder.addEventListener("stop", () => {
if (recordedChunks.length === 0) {
console.error("No recorded video available.");
return;
}
blob = new Blob(recordedChunks, { type: recordedChunks[0].type });
showRecordedVideo();
});
mediaRecorder.start();
}
How the JavaScript Works
-
Event Listener: We begin by placing event listeners so when the user clicks the record button, the
startScreenCapturing
function is triggered. - Screen and Audio Capture: The function checks if screen recording is supported by your browser. If so, it will request screen and audio permissions.
- Recording Process: After the user grants permission, the screen and audio streams are combined and recorded.
- Countdown Timer: A short countdown occurs before recording begins, giving users time to prepare.
- Stopping and Downloading: After the recording stops, the video is saved as a downloadable file accessible via the download link.
Frequently Asked Questions (FAQ)
Q: Can this screen recorder capture audio from the system?
- Yes, this project captures audio from both the system and the user's microphone. However, there are some browser limitations when it comes to capturing system audio due to security policies. So, check if your browser allows you to do this.
Q: Why can't I record my screen?
- If screen capturing isn't working, ensure your browser supports
navigator.mediaDevices.getDisplayMedia()
. Some older browsers may not support this API.
Q: What format is the video saved in?
- The video is saved in WebM format, which is widely supported by many modern browsers. You can convert it to MP4 or any other formats using various online tools.
Q: How do I improve the audio quality?
- The script requests audio with echo cancellation and noise suppression. Using an external microphone is recommended for better results.
Q: Can I pause the recording?
- Currently, there is no pause functionality. However, you can stop the recording and start a new one immediately.
Q: How large can the recorded files get?
- The file size depends on the length and quality of the recording. Short videos are typically small, but longer recordings may require more storage space.
Pros and Cons
Pros | Cons |
---|---|
Lightweight, no external libraries | Limited to modern browsers |
Simple to implement and understand | No advanced editing features |
Combines video and audio recording | Audio may not work on all devices |
Downloadable video in WebM format | File format may need conversion for sharing |
Responsive design | No real-time video preview during recording |
Top comments (0)