Feature Coming Soon!
The newsletter functionality is under development.
This project demonstrates a sophisticated Portfolio Carousel with synchronized sliders, built using HTML, CSS, and JavaScript with the Momentum Slider library. It creates an interactive and visually engaging way to showcase portfolio items, featuring multiple synchronized sliders for images, numbers, titles, and links. As the main image slider transitions, the corresponding numbers, titles, and "View Case" links also animate smoothly, providing a cohesive and rich user experience.
Key functionalities include horizontal image sliding, vertical synchronized sliding for numbers, titles, and links, and simple pagination for direct navigation. The design features a modern, dark theme with a subtle diagonal background effect. The Momentum Slider library handles the complex synchronization and animation logic, while CSS provides the aesthetic styling for the layout, typography, and interactive elements. This project is an excellent example of creating a highly polished and interactive portfolio presentation with a focus on synchronized content transitions.
The HTML structure for the Portfolio Carousel is designed to house the various synchronized sliders and navigation elements. It includes a `container` wrapping the entire layout, with a `header` for the logo and navigation menu, a `main` section for the sliders, and a `footer` for social links. The `sliders-container` within `main` is where the image, number, title, and link sliders are dynamically injected by JavaScript. A `pagination` list provides navigation buttons. This modular HTML setup allows the JavaScript to easily manipulate and synchronize the different content streams, creating a cohesive carousel experience.
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title> Portfolio Carousel with Synchronized Sliders - webstrom_tech</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
<link rel="stylesheet" href="./style.css">
</head>
<body>
<!-- partial:index.partial.html -->
<div class="container">
<header class="header">
<a class="header__logo">mir<span>r</span>or</a>
<nav class="header__menu">
<ul class="header__menu__list">
<li class="header__menu__item"><a class="header__menu__link">works</a></li>
<li class="header__menu__item"><a class="header__menu__link">culture</a></li>
<li class="header__menu__item"><a class="header__menu__link">news</a></li>
<li class="header__menu__item"><a class="header__menu__link">careers</a></li>
<li class="header__menu__item"><a class="header__menu__link">contact</a></li>
</ul>
</nav>
</header>
<!-- Container for all sliders, and pagination -->
<main class="sliders-container">
<!-- Here will be injected sliders for images, numbers, titles and links -->
<!-- Simple pagination for the slider -->
<ul class="pagination">
<li class="pagination__item"><a class="pagination__button"></a></li>
<li class="pagination__item"><a class="pagination__button"></a></li>
<li class="pagination__item"><a class="pagination__button"></a></li>
<li class="pagination__item"><a class="pagination__button"></a></li>
</ul>
</main>
<footer class="footer">
<nav class="footer__menu">
<ul class="footer__menu__list">
<li class="footer__menu__item"><a class="footer__menu__link">facebook</a></li>
<li class="footer__menu__item"><a class="footer__menu__link">dribbble</a></li>
<li class="footer__menu__item"><a class="footer__menu__link">instagram</a></li>
</ul>
</nav>
</footer>
</div>
<!-- partial -->
<script src='https://rawgit.com/lmgonzalves/momentum-slider/master/dist/momentum-slider.min.js'></script><script src="./script.js"></script>
</body>
</html>
The CSS for the Portfolio Carousel is designed to create a visually appealing and responsive layout, with specific styles for each synchronized slider. It includes global styles for the `body`, `a` tags, and the main `container`, which has a subtle diagonal background effect. The `header` and `footer` are styled for navigation and social links, respectively, with responsiveness handled by media queries. The core of the styling is applied to the various Momentum Slider components: `.ms--images` for the main image carousel, `.ms--numbers` for the large transparent numbers, `.ms--titles` for the project titles, and `.ms--links` for the "View Case" buttons. Each of these components has specific `width`, `height`, `position`, and `font-size` properties. The image slides use `background-image` for their content, and the pagination buttons are styled with `::before` and `::after` pseudo-elements to create a unique active state indicator. Media queries are extensively used to ensure the layout adapts gracefully to different screen sizes, adjusting positioning, font sizes, and visibility of elements for optimal presentation on mobile and desktop devices.
.ms--images {
position: relative;
overflow: hidden;
}
.ms--images.ms-container--horizontal {
width: 100%;
height: 400px;
max-width: 100%;
}
.ms--images.ms-container--horizontal .ms-track {
left: calc(50% - 350px);
}
.ms--images.ms-container--horizontal .ms-slide {
display: inline-flex;
}
.ms--images .ms-track {
display: flex;
position: absolute;
white-space: nowrap;
padding: 0;
margin: 0;
list-style: none;
}
.ms--images .ms-slide {
align-items: center;
justify-content: center;
width: 700px;
height: 400px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.ms--images {
left: calc(50% - 280px);
}
.ms--images.ms-container--horizontal .ms-track {
left: -70px;
}
.ms--images .ms-slide:nth-child(1) .ms-slide__image {
background-image: url("https://cdn.jsdelivr.net/gh/lmgonzalves/momentum-slider@3b3037f7f1bab402fe3c75cd20ab18e04e1cbe0b/portfolio-carousel/img/harvey-gibson-498362-unsplash.jpg");
}
.ms--images .ms-slide:nth-child(2) .ms-slide__image {
background-image: url("https://cdn.jsdelivr.net/gh/lmgonzalves/momentum-slider@3b3037f7f1bab402fe3c75cd20ab18e04e1cbe0b/portfolio-carousel/img/andre-hunter-461305-unsplash.jpg");
}
.ms--images .ms-slide:nth-child(3) .ms-slide__image {
background-image: url("https://cdn.jsdelivr.net/gh/lmgonzalves/momentum-slider@3b3037f7f1bab402fe3c75cd20ab18e04e1cbe0b/portfolio-carousel/img/joanna-nix-389128-unsplash.jpg");
}
.ms--images .ms-slide:nth-child(4) .ms-slide__image {
background-image: url("https://cdn.jsdelivr.net/gh/lmgonzalves/momentum-slider@3b3037f7f1bab402fe3c75cd20ab18e04e1cbe0b/portfolio-carousel/img/jurica-koletic-321003-unsplash.jpg");
}
.ms--images .ms-slide__image-container {
width: 80%;
height: 80%;
background-color: rgba(0, 0, 0, 0.3);
overflow: hidden;
}
.ms--images .ms-slide__image {
width: 100%;
height: 100%;
background-size: cover;
}
.ms--numbers {
position: relative;
overflow: hidden;
}
.ms--numbers.ms-container--horizontal {
width: 240px;
height: 240px;
max-width: 100%;
}
.ms--numbers.ms-container--horizontal .ms-track {
left: calc(50% - 120px);
}
.ms--numbers.ms-container--horizontal .ms-slide {
display: inline-flex;
}
.ms--numbers .ms-track {
display: flex;
position: absolute;
white-space: nowrap;
padding: 0;
margin: 0;
list-style: none;
}
.ms--numbers .ms-slide {
align-items: center;
justify-content: center;
width: 240px;
height: 240px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.ms--numbers {
position: absolute;
left: calc(50% - 380px);
top: calc(50% - 300px);
z-index: -1;
pointer-events: none;
}
.ms--numbers .ms-slide {
font-size: 9em;
font-weight: 900;
color: rgba(255, 255, 255, 0.2);
}
.ms--titles {
position: relative;
overflow: hidden;
}
.ms--titles.ms-container--vertical {
width: 400px;
height: 170px;
max-height: 100%;
}
.ms--titles.ms-container--vertical .ms-track {
flex-direction: column;
top: calc(50% - 85px);
}
.ms--titles.ms-container--vertical.ms-container--reverse .ms-track {
flex-direction: column-reverse;
top: auto;
bottom: calc(50% - 85px);
}
.ms--titles.ms-container--vertical .ms-slide {
display: flex;
}
.ms--titles .ms-track {
display: flex;
position: absolute;
white-space: nowrap;
padding: 0;
margin: 0;
list-style: none;
}
.ms--titles .ms-slide {
align-items: center;
justify-content: center;
width: 400px;
height: 170px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.ms--titles {
position: absolute;
left: calc(50% - 420px);
top: calc(50% - 85px);
z-index: 1;
pointer-events: none;
}
.ms--titles .ms-track {
white-space: normal;
}
.ms--titles .ms-slide {
font-size: 3.3em;
font-weight: 600;
}
.ms--titles .ms-slide h3 {
margin: 0;
text-shadow: 1px 1px 2px black;
}
.ms--links {
position: relative;
overflow: hidden;
}
.ms--links.ms-container--vertical {
width: 120px;
height: 60px;
max-height: 100%;
}
.ms--links.ms-container--vertical .ms-track {
flex-direction: column;
top: calc(50% - 30px);
}
.ms--links.ms-container--vertical .ms-slide {
display: flex;
}
.ms--links .ms-track {
display: flex;
position: absolute;
white-space: nowrap;
padding: 0;
margin: 0;
list-style: none;
}
.ms--links .ms-slide {
align-items: center;
justify-content: center;
width: 120px;
height: 60px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.ms--links {
position: absolute;
left: calc(50% - 420px);
top: calc(50% + 105px);
z-index: 1;
}
.ms--links .ms-track {
white-space: normal;
}
.ms--links .ms-slide__link {
font-weight: 600;
padding: 5px 0 8px;
border-bottom: 2px solid white;
cursor: pointer;
}
.pagination {
display: flex;
position: absolute;
left: calc(50% - 420px);
top: calc(100%);
list-style: none;
margin: 0;
padding: 0;
overflow: hidden;
z-index: 1;
}
.pagination__button {
display: inline-block;
position: relative;
width: 36px;
height: 20px;
margin: 0 5px;
cursor: pointer;
}
.pagination__button:before, .pagination__button:after {
content: "";
position: absolute;
left: 0;
top: calc(50% - 1px);
width: 100%;
box-shadow: 0 1px 0 #0B0D14;
}
.pagination__button:before {
height: 2px;
background-color: #6A3836;
}
.pagination__button:after {
height: 3px;
background-color: #DC4540;
opacity: 0;
transition: 0.5s opacity;
}
.pagination__item--active .pagination__button:after {
opacity: 1;
}
@media screen and (max-width: 860px) {
.ms--numbers {
left: calc(50% - 120px);
}
.ms--titles {
left: calc(50% - 200px);
top: calc(50% - 135px);
text-align: center;
}
.ms--links {
left: calc(50% - 60px);
top: calc(50% + 80px);
}
.pagination {
left: 50%;
top: calc(100% - 50px);
transform: translateX(-50%);
}
}
@media screen and (max-width: 600px) {
.ms--images {
overflow: visible;
}
}
@media screen and (max-width: 400px) {
.ms--titles .ms-slide {
transform: scale(0.8);
}
}
*, *:before, *:after {
box-sizing: border-box;
}
body {
color: white;
background-color: #1B1C21;
overflow: hidden;
}
a {
color: white;
text-decoration: none;
cursor: pointer;
}
.container {
position: relative;
display: flex;
flex-direction: column;
min-height: 100vh;
background-color: rgba(0, 0, 0, 0.1);
}
.container:before {
content: "";
position: absolute;
left: -150%;
top: 0;
width: 300%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
transform: rotate(45deg);
z-index: -1;
}
.header {
display: flex;
align-items: center;
padding: 30px;
}
.header__logo {
font-size: 1.3em;
font-weight: 900;
letter-spacing: -1px;
}
.header__logo span {
display: inline-block;
transform: translateY(4px) rotate(180deg);
pointer-events: none;
}
.header__menu {
margin-left: auto;
}
.header__menu__list, .footer__menu__list {
display: flex;
list-style: none;
margin: 0;
padding: 0;
}
.header__menu__link {
margin-left: 50px;
}
.footer {
display: flex;
justify-content: flex-end;
align-items: center;
padding: 30px;
}
.footer__menu__link {
margin-left: 50px;
color: rgba(255, 255, 255, 0.5);
}
.sliders-container {
position: relative;
display: flex;
align-items: center;
justify-content: center;
flex: 1;
}
@media screen and (max-width: 860px) {
.header__menu, .footer {
display: none;
}
}
The JavaScript for the Portfolio Carousel is responsible for initializing and synchronizing the multiple sliders using the Momentum Slider library. It starts by selecting the main `sliders-container`. Then, it initializes four separate Momentum Slider instances: `msNumbers` for the numerical pagination, `msTitles` for the project titles, `msLinks` for the "View Case" links, and `msImages` for the main image carousel. Each slider is configured with its specific CSS class, `range` (number of slides), `rangeContent` (how to render each slide's content), and `style` properties for animation. Crucially, `msImages` is configured to `sync` with `msNumbers`, `msTitles`, and `msLinks`, ensuring that all sliders move together. A `change` callback function is used to update the active state of the pagination items. Finally, an event listener on the `pagination` container allows users to click on a pagination button to directly select a corresponding slide in the `msImages` slider. This script orchestrates a complex, synchronized, and interactive carousel experience.
(function() {
var slidersContainer = document.querySelector('.sliders-container');
// Initializing the numbers slider
var msNumbers = new MomentumSlider({
el: slidersContainer,
cssClass: 'ms--numbers',
range: [1, 4],
rangeContent: function (i) {
return '0' + i;
},
style: {
transform: [{scale: [0.4, 1]}],
opacity: [0, 1]
},
interactive: false
});
// Initializing the titles slider
var titles = [
'King of the Ring Fight',
'Sound of Streets',
'Urban Fashion',
'Windy Sunset'
];
var msTitles = new MomentumSlider({
el: slidersContainer,
cssClass: 'ms--titles',
range: [0, 3],
rangeContent: function (i) {
return ''+ titles[i] +'
';
},
vertical: true,
reverse: true,
style: {
opacity: [0, 1]
},
interactive: false
});
// Initializing the links slider
var msLinks = new MomentumSlider({
el: slidersContainer,
cssClass: 'ms--links',
range: [0, 3],
rangeContent: function () {
return 'View Case';
},
vertical: true,
interactive: false
});
// Get pagination items
var pagination = document.querySelector('.pagination');
var paginationItems = [].slice.call(pagination.children);
// Initializing the images slider
var msImages = new MomentumSlider({
// Element to append the slider
el: slidersContainer,
// CSS class to reference the slider
cssClass: 'ms--images',
// Generate the 4 slides required
range: [0, 3],
rangeContent: function () {
return ' ';
},
// Syncronize the other sliders
sync: [msNumbers, msTitles, msLinks],
// Styles to interpolate as we move the slider
style: {
'.ms-slide__image': {
transform: [{scale: [1.5, 1]}]
}
},
// Update pagination if slider change
change: function(newIndex, oldIndex) {
if (typeof oldIndex !== 'undefined') {
paginationItems[oldIndex].classList.remove('pagination__item--active');
}
paginationItems[newIndex].classList.add('pagination__item--active');
}
});
// Select corresponding slider item when a pagination button is clicked
pagination.addEventListener('click', function(e) {
if (e.target.matches('.pagination__button')) {
var index = paginationItems.indexOf(e.target.parentNode);
msImages.select(index);
}
});
})();
Watch a live demonstration of the Portfolio Carousel below.
This Portfolio Carousel project is a sophisticated and visually compelling way to present creative work or any set of items that benefit from a synchronized, interactive display. By leveraging the Momentum Slider library, it achieves complex animations and content synchronization with relatively streamlined code. The responsive design ensures it looks great and functions smoothly across various devices, making it an excellent choice for modern portfolio websites, product showcases, or interactive presentations.
You can easily customize this component by:
When working with multiple synchronized sliders, carefully plan the data structure for your content. Keeping related data (image URL, title, link, number) grouped together will make it easier to manage and inject into the respective sliders, ensuring smooth synchronization.
Click the button below to download the full source code. Download will be ready in 10 seconds.
Receive coding tips and resources updates. No spam.
We respect your privacy. Unsubscribe at any time.