Learn how to design a sleek Neumorphism-style video player using HTML5, CSS, and JavaScript with this step-by-step tutorial.
Table of Contents
Neumorphism design, a rising trend in UI design, brings a fresh perspective to user interfaces with its soft shadows and subtle highlights. This design approach, often termed Soft UI, aims to replicate the tactile feel of physical objects within digital interfaces. In this tutorial, we will explore how to leverage HTML, CSS, and JavaScript to craft a sleek HTML5 video player adorned with Neumorphism design elements. Through step-by-step instructions, you'll learn how to create an engaging and visually appealing video player that seamlessly integrates modern design aesthetics with functional interactivity. Let's dive in and transform your web development skills with this innovative approach to video player design.
Source Code
Step 1 (HTML Code):
Start by creating the basic HTML structure for the video player. This includes elements such as <video> for embedding the video, controls for play/pause, volume, progress bar, etc.
Here's a breakdown of the different sections:
1. Document Type Declaration: <!DOCTYPE html> declares the document type and version of HTML being used, which is HTML5 in this case.
2. HTML Structure: The <html> element marks the beginning and end of the HTML document. The lang attribute specifies the language of the document, which is set to English (en).
3. Head Section: Contains metadata and links to external resources. Here's what's included:
- Character Encoding: <meta charset="UTF-8"> specifies the character encoding for the document as UTF-8, which supports a wide range of characters.
- Compatibility Meta Tag: <meta http-equiv="X-UA-Compatible" content="IE=edge"> ensures that the webpage renders in the highest mode available in Internet Explorer.
- Viewport Meta Tag: <meta name="viewport" content="width=device-width, initial-scale=1.0"> sets the viewport width to the device width and initial zoom level to 1.0, ensuring proper rendering on various devices.
- Title: <title>Neumorphism Video Player</title> sets the title of the webpage.
- External CSS: Two external CSS files are linked using <link> tags. One is for Bootstrap, a popular CSS framework, and the other is for Font Awesome, a library of icons. Additionally, a local CSS file styles.css is linked for custom styles.
4. Body Section: Contains the visible content of the webpage.
- Div with Class "box": Contains the main content of the webpage. It has a class of "text-center" for center alignment and a dir attribute set to "ltr" (left-to-right directionality).
- Heading: <h4 class="display-2 text-center main">Neu player</h4> displays a heading with the text "Neu player". It has classes for styling purposes.
- Video Player: The main part of the webpage is a video player contained within a <div> element with class "neo-video-player" and id "popout-video-player". It includes various controls such as a play button, volume control, progress bar, download button, playback speed control, and fullscreen button. The actual video element <video> is embedded with a source pointing to an MP4 video file hosted on w3schools.com.
5. Scripts: JavaScript files are included for functionality. Two external scripts are linked using <script> tags. One is jQuery, a JavaScript library, and the other is a local script file script.js.
Step 2 (CSS Code):
Utilize CSS to apply Neumorphism design principles to the video player elements. This involves adding soft shadows, highlights, and gradients to create a three-dimensional effect.
let's break down the CSS code step by step:
1. Body Styles:
- Sets the background color of the body to a light grayish-blue (#eff0f4).
- Sets the text color to a dark gray (#575757).
2. .box Styles:
- Defines a CSS class called ".box".
- Sets the maximum width of the box to 600 pixels.
- Centers the box horizontally using the auto margin property.
3. Link Styles:
- Sets the color of all links to the same dark gray as the body text.
- Defines a hover effect for links: changes the color to a shade of orange (#FD9644) and removes the default underline text decoration.
4. .main Styles:
- Defines a CSS class called ".main".
- Sets the text color to a bright orange (#FD9644).
- Sets the opacity of the text to 0.2 (20% visibility).
- Sets the font weight to 900 (bold).
- Moves the text upwards by 30 pixels (negative margin) to overlap with the previous element.
5. .neo-video-player Styles:
- Defines a CSS class called ".neo-video-player" for styling video player elements.
- Sets the position to relative.
- Ensures that any content overflowing the box is hidden.
- Sets the width to 100% and centers the box horizontally.
- Rounds the corners with a border radius of 10 pixels.
- Applies a box shadow to simulate depth.
6. .video-control-part, .video-control-part > div, .video-neu-btn Styles:
- Target elements within the video control section for styling.
- Sets them to display as flex containers with items aligned vertically.
7. .video-control-part Styles:
- Positions the control part at the bottom of the video player.
- Sets the background color to the same as the body.
- Defines a transition effect for smooth changes.
- Sets the opacity to 1 and adds padding.
8. .video-control-part.playing Styles:
- Overrides the opacity property when the video is playing, making the control part transparent.
9. Hover Effect on Video Player:
- Changes the opacity of the control part to fully visible when hovering over the video player.
10. Styles for Video Control Buttons:
- Defines styles for control buttons with rounded corners, shadows, and hover effects.
- Applies special styles for different button states such as mute, pause, etc.
- Sets the content for pseudo-elements to display specific icons.
11. Styles for Progress Bar:
- Defines styles for progress bars and their components such as background, progress indicator, and pin.
12. Styles for Sound Control:
- Defines a box for sound control with transition effects.
- Changes the width and opacity on hover to reveal the sound control box.
13. .drop-btn Styles:
- Defines styles for a drop-down button, removing background and box shadow.
- Overrides background and shadow for the nested video-neu-btn.
14. .play-btn.pause Styles:
- Defines styles for the play button when in a paused state.
- Sets a gradient background and hides the content before the button.
15. .play-btn Styles:
- Defines styles for the play button, including its width and height.
- Sets the content to display a play icon.
16. .sound-btn Styles:
- Defines styles for the sound button and its variations (low volume, mute).
- Sets content to display volume-related icons.
17. .download-btn, .setting-btn, .fullscreen-btn Styles:
- Defines styles for buttons related to download, settings, and fullscreen modes.
- Sets content to display corresponding icons.
18. .bar-bg Styles:
- Styles the background of the progress bar, including its color, border radius, and box-shadow.
19. .bar-time Styles:
- Styles the time indicator within the progress bar, including its color, border radius, and box-shadow.
20. .bar-pin Styles:
- Styles the pin that marks the current progress within the progress bar.
21. .video-element Styles:
- Styles the video element itself, ensuring it takes up the full width and adjusts to smaller screen sizes.
22. .box-sound Styles:
- Styles the sound control box, setting its initial width to 0 and opacity to 0 to hide it.
- Applies a transition effect for smooth visibility changes.
23. .fastFwd-box Styles:
- Styles the fast-forward box, positioning it relative to its parent and adding a border and border radius.
- Sets display to none by default and shows it on hover over the setting button.
24. .bar-time-box Styles:
- Styles the time display box, positioning it relative to its parent and adding a border and border-radius.
- Sets the display to none by default and shows it on hover over the progress bar.
25. Focus Styling:
- Removes the default focus styling for the fast-forward button.
body {
background-color: #eff0f4;
color: #575757;
}
.box {
max-width: 600px;
margin: auto;
}
a {
color: #575757;
}
a:hover {
color: #FD9644;
text-decoration: none;
}
.main {
color: #FD9644;
opacity: 0.2;
font-weight: 900;
margin-bottom: -30px;
}
.neo-video-player {
position: relative;
overflow: hidden;
width: 100%;
margin: auto;
border-radius: 10px;
box-shadow: 15px 15px 29px #cbcccf,
-15px -15px 29px #ffffff;
}
.video-control-part, .video-control-part > div, .video-neu-btn {
display: flex;
align-items: center;
}
.video-control-part {
justify-content: space-between;
position: absolute;
left: 0;
right: 0;
bottom: 0;
z-index: 5;
opacity: 1;
padding: 10px 15px;
background-color: #EFF0F4;
transition: all .25s ease;
}
.video-control-part.playing {
opacity: 0;
}
.neo-video-player:hover .video-control-part {
opacity: 1;
}
.video-neu-btn {
position: relative;
justify-content: center;
align-items: center;
border-radius: 50px;
background: #EFF0F4;
box-shadow: 6px 6px 15px #cbcccf,
-6px -6px 15px #ffffff;
width: 40px;
height: 40px;
margin: 5px;
}
.video-neu-btn::before {
content: '';
background: linear-gradient(145deg, #ffffff, #d7d8dc);
border-radius: 100%;
position: absolute;
top: 3px;
left: 3px;
right: 3px;
bottom: 3px;
transition: all .25s ease;
}
.video-neu-btn::after {
font-family: 'Font Awesome 5 Free';
font-weight: 900;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
display: inline-block;
font-style: normal;
font-variant: normal;
text-rendering: auto;
line-height: 1;
z-index: 1;
transition: all .25s ease;
}
.drop-btn > .video-neu-btn {
background: none;
box-shadow: none;
}
.drop-btn > .video-neu-btn::before {
background: none;
}
.video-neu-btn:hover::before {
opacity: 0;
}
.video-neu-btn:hover::after {
color: #FD9644;
}
/* toggle style */
.play-btn.pause {
background: linear-gradient(145deg, #e4873d, #ffa149);
}
.play-btn.pause::before {
opacity: 0;
}
.play-btn.pause::after {
color: #EFF0F4;
}
.play-btn.pause:hover::after {
color: #575757;
}
/* set icon */
.play-btn {
width: 60px;
height: 60px;
}
.play-btn::after {
content: '\f04b';
}
.play-btn.pause::after {
content: '\f04c';
}
.sound-btn::after {
content: '\f028';
}
.sound-btn.low::after {
content: '\f027';
}
.sound-btn.mute::after {
content: '\f6a9';
}
.download-btn::after {
content: '\f381';
}
.setting-btn::after {
content: '\f013';
}
.fullscreen-btn::after {
content: '\f065';
}
.video-control-bar-part, .bar-bg {
width: 100%;
}
.bar-bg {
border-radius: 50px;
height: 10px;
background: #EFF0F4;
box-shadow: inset 2px 2px 4px #cbcccf, inset -2px -2px 4px #ffffff;
margin: 0 10px;
}
.bar-time {
position: relative;
height: 10px;
border-radius: 50px;
background: #FD9644;
box-shadow: inset 3px 3px 6px #d7803a, inset -3px -3px 6px #ffad4e;
width: 0%;
}
.bar-progress {
height: 10px;
width: 100%;
}
.bar-pin {
position: absolute;
width: 20px;
height: 20px;
background: #EFF0F4;
box-shadow: 4px 4px 10px #cbcccf, -4px -4px 10px #ffffff;
border-radius: 50px;
right: -10px;
top: -5px;
}
.video-element {
width: 100%;
min-width: 100%;
margin-bottom: -10px;
}
.box-sound {
width: 0px;
opacity: 0;
overflow: hidden;
background: #EFF0F4;
height: 40px;
padding: 17px 15px 0 40px;
position: absolute;
left: 0;
z-index: 1;
border-radius: 50px;
box-shadow: 6px 6px 15px #cbcccf, -6px -6px 15px #ffffff;
transition: all .25s ease;
}
.drop-btn:hover .box-sound {
width: 120px;
opacity: 1;
}
.volume {
width: 100%;
height: 5px;
background: #EFF0F4;
border-radius: 50px;
box-shadow: inset 2px 2px 3px #cbcccf, inset -2px -2px 3px #ffffff;
}
.bar-volume {
width: 100%;
height: 5px;
border-radius: 50px;
background: #FD9644;
box-shadow: inset 3px 3px 6px #d7803a, inset -3px -3px 6px #ffad4e;
}
.fastFwd-box {
display: none;
position: absolute;
width: max-content;
top: -40px;
right: 0;
background: #eff0f4;
border: 1px solid #00000026;
border-radius: 10px;
}
.setting-btn:hover .fastFwd-box {
display: block;
}
.fastFwd-box::before {
content: '';
width: 10px;
height: 10px;
background: #eff0f4;
display: block;
position: absolute;
bottom: -6px;
right: 12px;
transform: rotate(45deg);
border: solid #00000026;
border-width: 0 1px 1px 0;
}
.fastFwd:focus {
box-shadow: none;
}
.bar-time-box {
display: none;
position: absolute;
width: max-content;
top: -65px;
right: -55px;
background: #eff0f4;
border-radius: 10px;
padding: 10px;
border: 1px solid #00000026;
}
.bar-progress:hover .bar-time-box {
display: block;
}
.bar-time-box::before {
content: '';
width: 10px;
height: 10px;
background: #eff0f4;
display: block;
position: absolute;
bottom: -6px;
right: 47%;
transform: rotate(45deg);
border: solid #00000026;
border-width: 0 1px 1px 0;
}
Step 3 (JavaScript Code):
Enhance the video player with JavaScript to make it interactive and functional. This includes implementing features like autoplay, fullscreen mode, custom controls, and responsiveness.
Let's break down the code step by step:
1. Initialization: The code iterates over all elements with the class name "neo-video-player" using jQuery's each() function. Inside the loop, it sets up various variables to reference different elements within each video player.
2. Setting Download Link: It sets up a download link for the video by extracting the video source URL and assigning it to the href attribute of an element with the ID "download-video".
3. Defining Functions:
- playVideo(): Toggles between playing and pausing the video when called.
- updateVolume(x, vol): Updates the volume of the video based on the mouse position or specified volume value.
- changeSpeed(): Changes the playback speed of the video.
- launchFullscreen(): Requests the browser to enter fullscreen mode when called.
- time_format(seconds): Formats the time in seconds into minutes and seconds.
- startBuffer(): Tracks the buffer progress of the video.
- updatebar(x): Updates the progress bar of the video.
4. Event Handlers:
- Various event handlers are set up to handle interactions with different controls of the video player such as play/pause button clicks, volume control, fast forward button, full-screen mode, and progress bar seeking.
5. Video Events Handling:
- Event handlers are set up to update the current time and duration of the video, and to control the display of controls based on user interactions and video playback state.
6. Video Controls Interaction:
- The code manages the interaction of different video controls such as play/pause button, volume control, full-screen mode, and progress bar seeking, ensuring proper functionality and user experience.
$(".neo-video-player").each(function() {
// Video
var $video_container = $(this);
var $video = $(this).find("#video-element");
// set download link
$('#download-video').attr('href', $('#video-element source').attr('src'));
// Video Controls
var $video_controls = $(this).find(".video-control-part");
var $progress_bar = $(this).find(".bar-progress");
var $progress = $(this).find(".bar-time");
var $buffer_bar = $(this).find(".bar-buffer");
var $play_button = $(this).find(".play-btn");
var $sound_button = $(this).find(".sound-btn");
var $volume_wrapper = $(this).find(".volume");
var $volume_bar = $(this).find(".bar-volume");
var $full_screen_btn = $(this).find(".fullscreen-btn");
var $current = $(this).find(".current");
var $duration = $(this).find(".duration");
var $fast_fwd = $(this).find(".fastFwd");
// Toggles play/pause for the video
function playVideo() {
if ($video[0].paused) {
$video[0].play();
$video_controls.addClass("playing");
$play_button.addClass("pause");
if ($video_container.parents(".video-header").length) {
$video_container.parents(".video-header").addClass("playing");
}
} else {
$video[0].pause();
$video_controls.removeClass("playing");
$play_button.removeClass("pause");
$video_container.parents(".video-header").removeClass("playing");
}
}
function updateVolume(x, vol) {
if (vol) {
$percentage = vol * 100;
} else {
$position = x - $volume_wrapper.offset().left;
$percentage = 100 * $position / $volume_wrapper.width();
}
if ($percentage > 100) {
$percentage = 100;
}
if ($percentage < 0) {
$percentage = 0;
}
//update volume bar and video volume
$volume_bar.css("width", $percentage + "%");
$video[0].volume = $percentage / 100;
if ($video[0].volume == 0) {
$sound_button.addClass("mute");
} else if ($video[0].volume > 0.5) {
$sound_button.removeClass("mute").removeClass("low");
} else {
$sound_button.removeClass("mute").addClass("low");
}
}
function changeSpeed() {
if ($video[0].playbackRate === 1) {
$video[0].playbackRate = 1.25;
$fast_fwd.val("Speed : 1.25x");
} else if ($video[0].playbackRate === 1.25) {
$video[0].playbackRate = 1.5;
$fast_fwd.val("Speed : 1.5x");
} else if ($video[0].playbackRate === 1.5) {
$video[0].playbackRate = 1.75;
$fast_fwd.val("Speed : 1.75x");
} else if ($video[0].playbackRate === 1.75) {
$video[0].playbackRate = 2;
$fast_fwd.val("Speed : 2x");
} else if ($video[0].playbackRate === 2) {
$video[0].playbackRate = 1;
$fast_fwd.val("Speed : 1x");
}
}
function launchFullscreen() {
if ($video[0].requestFullscreen) {
$video[0].requestFullscreen();
} else if ($video[0].mozRequestFullScreen) {
$video[0].mozRequestFullScreen();
} else if ($video[0].webkitRequestFullscreen) {
$video[0].webkitRequestFullscreen();
} else if ($video[0].msRequestFullscreen) {
$video[0].msRequestFullscreen();
}
}
function time_format(seconds) {
var m = Math.floor(seconds / 60) < 10
? "0" + Math.floor(seconds / 60)
: Math.floor(seconds / 60);
var s = Math.floor(seconds - m * 60) < 10
? "0" + Math.floor(seconds - m * 60)
: Math.floor(seconds - m * 60);
return m + ":" + s;
}
function startBuffer() {
$current_buffer = $video[0].buffered.end(0);
$max_duration = $video[0].duration;
$perc = 100 * $current_buffer / $max_duration;
$buffer_bar.css("width", $perc + "%");
if ($current_buffer < $max_duration) {
setTimeout(startBuffer, 500);
}
}
function updatebar(x) {
$position = x - $progress.offset().left;
$percentage = 100 * $position / $progress_bar.width();
if ($percentage > 100) {
$percentage = 100;
}
if ($percentage < 0) {
$percentage = 0;
}
$progress.css("width", $percentage + "%");
$video[0].currentTime = $video[0].duration * $percentage / 100;
}
$video.on("loadedmetadata", function() {
$current.text(time_format(0));
$duration.text(time_format($video[0].duration));
updateVolume(0, 0.7);
setTimeout(startBuffer, 150);
});
// Play/pause on video click
$video.click(function() {
playVideo();
});
// Video duration timer
$video.on("timeupdate", function() {
$current.text(time_format($video[0].currentTime));
$duration.text(time_format($video[0].duration));
var currentPos = $video[0].currentTime;
var maxduration = $video[0].duration;
var perc = 100 * $video[0].currentTime / $video[0].duration;
$progress.css("width", perc + "%");
});
/* VIDEO CONTROLS
------------------------------------------------------- */
// Hide button controls when video is playing
$video_container.on("mouseleave", function() {
if ($video[0].paused === false) {
$video_container.addClass("playing");
}
});
// Show button controls on hover
$video_container.on("mouseover", function() {});
// Play/pause on button click
$play_button.click(function() {
playVideo();
});
// Fast Forward Button
$fast_fwd.click(function() {
changeSpeed();
});
// Volume Drag
var volumeDrag = false;
$volume_wrapper.on("mousedown", function(e) {
volumeDrag = true;
$video[0].muted = false;
$sound_button.removeClass("mute");
updateVolume(e.pageX);
});
$(document).on("mouseup", function(e) {
if (volumeDrag) {
volumeDrag = false;
updateVolume(e.pageX);
}
});
$(document).on("mousemove", function(e) {
if (volumeDrag) {
updateVolume(e.pageX);
}
});
// Mute video on button click
$sound_button.click(function() {
$video[0].muted = !$video[0].muted;
$(this).toggleClass("mute");
if ($video[0].muted) {
$volume_bar.css("width", 0);
} else {
$volume_bar.css("width", $video[0].volume * 100 + "%");
}
});
// Full Screen Button
$full_screen_btn.click(function() {
launchFullscreen();
});
// VIDEO PROGRESS BAR
//when video timebar clicked
var timeDrag = false; /* check for drag event */
$progress_bar.on("mousedown", function(e) {
timeDrag = true;
updatebar(e.pageX);
});
$(document).on("mouseup", function(e) {
if (timeDrag) {
timeDrag = false;
updatebar(e.pageX);
}
});
$(document).on("mousemove", function(e) {
if (timeDrag) {
updatebar(e.pageX);
}
});
});
Final Output:
Conclusion:
In conclusion, mastering the creation of an HTML5 video player with Neumorphism design elements opens up a world of possibilities in web development. By combining the power of HTML, CSS, and JavaScript, you can elevate your projects with visually stunning and user-friendly interfaces. Throughout this tutorial, we've covered the fundamental steps of setting up the HTML structure, styling with CSS to achieve the Neumorphism effect, and adding JavaScript functionality for enhanced interactivity.
As you continue to explore and experiment with Neumorphism design principles, don't hesitate to push the boundaries of creativity and innovation. Consider integrating additional features, refining the design elements, and optimizing the player's performance to meet the evolving needs of your users.
Remember, the journey to mastery is ongoing. Stay curious, keep learning, and embrace the endless possibilities of web development. With dedication and practice, you'll unlock the potential to create captivating experiences that leave a lasting impression. Start building your own Neumorphism-style video player today and embark on a rewarding journey of design and development excellence.
Code by: 47vigen
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 😊