back to top

About

X-Project Components - is a collection of the most useful components for page layout. For each component are presented description and code examples with the help of which you can easily understand and apply the right component on your website. In X-Project Components all css code was written by SASS (with SCSS syntax) and all javascript code with the use of a library jQuery.

All css code for components was written using BEM naming, meaning .block-name for independent block, .block-name__element-name for elements inside that block. And .-modifier-name for modifiers of the block. For javascript hooks was used prefix .js-*.

Every component are checked for validity through validator.w3.org, tested for сross-browser compatibility through browserstack.com, and works in the latest versions of all popular browsers (including IE11).

How to use

1) To start working with the X-Project Components you must to include jQuery library before your javascript code:

							
								<!-- jQuery library -->
								<script src="/path/to/jquery.js"></script>

								<!-- Your JS file -->
								<script src="/path/to/common.js"></script>
							
						

2) Also you should have SASS compiler (for example Prepros or Gulp) for compiling your CSS.

3) Find the right component and copy it to your project.

Changelog

Changes Date

A little refactoring of all components. Added Hamburger menu, Viewport units on mobile and Background video components.

24.03.2021

Refactoring of all components.

17.10.2019

Added SVG animation component.

25.07.2018

Fixed Count Up and Progress bars components (for the count up numbers used countUp.js), added HTML map marker component.

17.06.2018

Added count up component, added function for scroll bar compensation, fixed decimal converting in progress bars

20.05.2018

Added progress bars component

09.05.2018

Added shuffle filter component

01.05.2018

Added preloader component

15.04.2018

Components

Preloader HTML SASS JS

Adding a preloader to the site with few lines of jQuery code. It displays a loading animation until the browser fetched the whole webcontent and will fade out the moment the page has been completely loaded. It is recommended to insert this code first, before all other user scripts.

																
																	$preloader-overlay-bg-color: #FFFFFF;

																	.preloader-overlay {
																		position: fixed;
																		top: 0;
																		left: 0;
																		right: 0;
																		bottom: 0;
																		width: 100%;
																		height: 100%;
																		background: $preloader-overlay-bg-color;
																		z-index: 9999;

																		&__preloader-item {
																			position: absolute;
																			top: 50%;
																			left: 50%;
																			transform: translate(-50%, -50%);
																		}
																	}

																	// styles for preloader item
																	.preloader-item {
																		height: 50px;
																		width: 50px;
																		border: 5px solid rgba(#000000, 0.3);
																		border-top: 5px solid #000000;
																		border-radius: 50%;
																		animation: rotate 1s infinite linear;
																	}

																	@keyframes rotate {
																		0% {
																			transform: translate(-50%, -50%) rotate(0deg);
																		}

																		100% {
																			transform: translate(-50%, -50%) rotate(360deg);
																		}
																	}
																
															
																
																	// PRELOADER
																	function initPreloader() {
																		var preloader = $('.js-preloader'),
																				hideTimeout = 1000;

																		// hide preloader by click
																		preloader.on('click', function() {
																			$(this).fadeOut('slow');
																		});

																		$(window).on('load', function() {
																			// hide preloader
																			setTimeout(function() {
																				preloader.fadeOut('slow');
																			}, hideTimeout);
																		});
																	}

																	initPreloader();
																
															

Hamburger menu HTML SASS JS

Animated hamburger menu icon. The sizes of the hamburger menu are set via scss variables.

																
																	$bar-width: 50px;
																	$bar-height: 4px;
																	$bar-spacing: 8px;
																	$bar-border-radius: 0;
																	$bar-color: #000000;
																	$opening-time: 600ms;

																	.hamburger-menu {
																		position: relative;
																		display: inline-block;
																		width: $bar-width;
																		height: $bar-width;
																		text-decoration: none;
																		padding: 0;
																		background-color: transparent;
																		border: none;

																		&.-active {
																			.hamburger-menu__bars {
																				background-color: rgba($bar-color, 0);

																				&:before {
																					visibility: visible;
																					bottom: 0;
																					transform: rotate(-45deg);
																					transition: bottom $opening-time * 0.5 cubic-bezier(0.23, 1, 0.32, 1), transform $opening-time * 0.5 $opening-time * 0.5 cubic-bezier(0.23, 1, 0.32, 1);
																				}

																				&:after {
																					visibility: visible;
																					top: 0;
																					transform: rotate(45deg);
																					transition: top $opening-time * 0.5 cubic-bezier(0.23, 1, 0.32, 1), transform $opening-time * 0.5 $opening-time * 0.5 cubic-bezier(0.23, 1, 0.32, 1);
																				}
																			}
																		}

																		&.-without-animation {
																			.hamburger-menu__bars,
																			.hamburger-menu__bars:before,
																			.hamburger-menu__bars:after {
																				transition: none;
																			}
																		}

																		&__wrap {
																			position: absolute;
																			top: 50%;
																			left: 50%;
																			transform: translate(-50%, -50%);
																			width: $bar-width;
																			height: $bar-height * 3 + $bar-spacing * 2;
																		}

																		&__bars,
																		&__bars:before,
																		&__bars:after {
																			width: $bar-width;
																			height: $bar-height;
																			background-color: $bar-color;
																			border-radius: $bar-border-radius;
																		}

																		&__bars {
																			position: absolute;
																			top: 50%;
																			left: 50%;
																			transform: translate(-50%, -50%);
																			transition: background-color 0ms $opening-time * 0.5;

																			&:before {
																				content: "";
																				position: absolute;
																				left: 0;
																				bottom: $bar-spacing + $bar-height;
																				transition: bottom $opening-time * 0.5 $opening-time * 0.5 cubic-bezier(0.23, 1, 0.32, 1), transform $opening-time * 0.5 cubic-bezier(0.23, 1, 0.32, 1);
																				visibility: visible;
																			}

																			&:after {
																				content: "";
																				position: absolute;
																				left: 0;
																				top: $bar-spacing + $bar-height;
																				transition: top $opening-time * 0.5 $opening-time * 0.5 cubic-bezier(0.23, 1, 0.32, 1), transform $opening-time * 0.5 cubic-bezier(0.23, 1, 0.32, 1);
																				visibility: visible;
																			}
																		}
																	}
																
															
																
																	// HAMBURGER MENU
																	function initHamburgerMenu() {
																		var hamburgerMenu = $('.js-hamburger-menu');

																		function openMenu() {
																			hamburgerMenu.addClass('-active');
																		}

																		function closeMenu() {
																			hamburgerMenu.removeClass('-active');
																		}

																		hamburgerMenu.on('click', function(e) {
																			e.preventDefault();

																			if (!$(this).hasClass('-active')) {
																				openMenu();
																			} else {
																				closeMenu();
																			}
																		});

																		// close with escape key
																		$(document).keyup(function(e) {
																			if (e.keyCode == 27) {
																				closeMenu();
																			}
																		});
																	}

																	initHamburgerMenu();
																
															

Stop animations during window resizing SASS JQUERY JS

Say you have page that has a bunch of transitions and animations on all sorts of elements. Some of them get triggered when the window is resized because they have to do with size of the page or position or padding or something. It doesn’t really matter what it is, the fact that the transition or animation runs may contribute to a feeling of jankiness as you resize the window. If those transitions or animations don’t deliver any benefit in those scenarios, you can turn them off!

																
																	.resize-animation-stopper * {
																		animation: none !important;
																		transition: none !important;
																	}
																
															
																
																	// STOP ANIMATIONS DURING WINDOW RESIZING
																	function initStopAnimationsDuringWindowResizing() {
																		var resizeTimer;

																		$(window).on('resize', function() {
																			$('body').addClass('resize-animation-stopper');

																			clearTimeout(resizeTimer);

																			resizeTimer = setTimeout(function() {
																				$('body').removeClass('resize-animation-stopper');
																			}, 400);
																		});
																	}

																	initStopAnimationsDuringWindowResizing();
																
															
																
																	// STOP ANIMATIONS DURING WINDOW RESIZING
																	let initStopAnimationsDuringWindowResizing = () => {
																		let resizeTimer;

																		window.addEventListener('resize', () => {
																			document.body.classList.add('resize-animation-stopper');

																			clearTimeout(resizeTimer);

																			resizeTimer = setTimeout(() => {
																				document.body.classList.remove('resize-animation-stopper');
																			}, 400);
																		});
																	}

																	initStopAnimationsDuringWindowResizing();
																
															

Only numeric input JQUERY JS

Quick way to set an HTML text input to only allow numeric keystrokes

																
																	// ONLY NUMERIC INPUT
																	function initOnlyNumericInput() {
																		$('.js-only-numeric-input').on('input', function() {
																			this.value = this.value.replace(/[^\d]/g, '');
																		});
																	}

																	initOnlyNumericInput();
																
															
																
																	// ONLY NUMERIC INPUT
																	let initOnlyNumericInput = () => {
																		let inputElement = document.getElementsByClassName('js-only-numeric-input')[0];

																		if (typeof(inputElement) != 'undefined' && inputElement != null) {
																			inputElement.addEventListener('input', function() {
																				this.value = this.value.replace(/[^\d]/g, '');
																			});
																		}
																	}

																	initOnlyNumericInput();
																
															

Viewport units on mobile SASS JS

The trick to viewport units on mobile.

																
																	.menu {
																		height: 100vh; /* Fallback for browsers that do not support Custom Properties */
																		height: calc(var(--vh, 1vh) * 100);
																	}
																
															
																
																	// VIEWPORT UNITS ON MOBILE
																	function initViewportUnitsOnMobile() {
																		var vh = window.innerHeight * 0.01;
																		document.documentElement.style.setProperty('--vh', vh + 'px');

																		$(window).on('resize', function() {
																			vh = window.innerHeight * 0.01;
																			document.documentElement.style.setProperty('--vh', vh + 'px');
																		});
																	}

																	initViewportUnitsOnMobile();
																
															

SVG animation HTML SASS JS

Animating SVG paths to animate the drawing sequence. The animation triggered as soon as you have scrolled to the element.

This component is dependent on vivus.js, and waypoints.js.

Icons should be specially prepared (ensure there are no fills).

														
															<script src="/path/to/vivus.js"></script>
															<script src="/path/to/waypoints.js"></script>
															<script src="/path/to/common.js"></script>
														
													
																
																	.svg-animation-item {
																		fill: none;

																		path {
																			stroke-width: 4;
																			stroke: transparent;
																		}

																		&.-animation-init {
																			path {
																				stroke: inherit;
																			}
																		}

																		// COLORS
																		&.-purple {
																			stroke: #4C4E6D;
																		}
																	}
																
															
																
																	// SVG ANIMATION
																	function initSvgAnimation() {
																		function svgAnimation(svgItem, duration) {
																			$(svgItem).addClass('-animation-init');

																			new Vivus(svgItem, {
																				duration: duration,
																				type: 'oneByOne'
																			});
																		}

																		function svgAnimationOnScroll() {
																			var svgItem = $('.js-svg-animation-item');

																			if (svgItem.length) {
																				svgItem.waypoint({
																					handler: function() {
																						if (!this.element.svgAnimationInit) {
																							this.element.svgAnimationInit = true;

																							svgAnimation(this.element, 300)
																						}
																					},
																					offset: '80%'
																				})
																			}
																		}

																		svgAnimationOnScroll();
																	}

																	initSvgAnimation();
																
															

Count up HTML JS

Animates a number from zero to end value, which is triggered when you scroll to an target element. In example for a grid is used Bootstrap.

0%

0%

0%

This component is dependent on countUp.umd.js, and waypoints.js.

														
															<script src="/path/to/countUp.umd.js"></script>
															<script src="/path/to/waypoints.js"></script>
															<script src="/path/to/common.js"></script>
														
													
																
																	// STYLES FOR AN EXAMPLE - REMOVE/EDIT AFTER COPYING

																	.count-up-item {
																		font-size: 40px;
																		margin-bottom: 0;
																		text-align: center;
																	}
																
															
																
																	// COUNT UP
																	function initCountUp() {
																		function countUpNumbers(countUpItem, duration) {
																			var countNumber = $(countUpItem).attr('data-count-number'),
																					numbersAfterComma = 0;

																			if (countNumber.indexOf('.') > 0) {
																				numbersAfterComma = countNumber.length - (countNumber.indexOf('.') + 1);
																			} else if (countNumber.indexOf(',') > 0) {
																				numbersAfterComma = countNumber.length - (countNumber.indexOf(',') + 1);
																			}

																			var options = {
																				startVal: 0,
																				decimalPlaces: numbersAfterComma,
																				duration: duration/1000,
																				useEasing: true,
																				decimal: '.',
																				suffix: '%'
																			};

																			new countUp.CountUp(countUpItem, countNumber, options).start();
																		}

																		function countUpNumbersOnScroll() {
																			var countUpItem = $('.js-count-up-item');

																			if (countUpItem.length) {
																				countUpItem.waypoint({
																					handler: function() {
																						if (!this.element.countUpInit) {
																							this.element.countUpInit = true;

																							countUpNumbers(this.element, 8000);
																						}
																					},
																					offset: '80%'
																				})
																			}
																		}

																		countUpNumbersOnScroll();
																	}

																	initCountUp();
																
															

Progress bars HTML SASS JS

Сreating animated progress bars, which triggered as soon as you scrolling to an element.

Sketch
0%
Photoshop
0%
Illustrator
0%
Principle
0%

This component is dependent on countUp.umd.js, and waypoints.js.

														
															<script src="/path/to/countUp.umd.js"></script>
															<script src="/path/to/waypoints.js"></script>
															<script src="/path/to/common.js"></script>
														
													
																
																	.progress-bar-item {
																		display: flex;
																		align-items: center;

																		&__title {
																			flex-basis: 120px;
																			padding-right: 15px;
																			margin-bottom: 0;
																			line-height: 1;
																		}

																		&__strip-wrap {
																			width: 100%;
																			overflow: hidden;
																			flex-basis: 0;
																			flex-grow: 1;
																		}
																	}

																	.progress-bar-strip {
																		position: relative;
																		width: 0;
																		height: 20px;
																		background-color: #4C4E6C;

																		&__percent {
																			position: absolute;
																			top: 50%;
																			right: 5px;
																			transform: translate(0, -50%);
																			color: #fff;
																			white-space: nowrap;
																		}
																	}

																	.progress-bars-wrap {
																		&__item {
																			margin-bottom: 10px;

																			&:last-child {
																				margin-bottom: 0;
																			}
																		}
																	}
																
															
																
																	// PROGRESS BARS
																	function initProgressBars() {
																		function progressBars(progressBarsBlock, duration) {
																			var progressBarItem = $(progressBarsBlock).find('.js-progress-bar-item');

																			progressBarItem.each(function() {
																				var progressBarsFillItem = $(this).find('.js-progress-bar-strip'),
																						progressBarsCountUpItem = $(this).find('.js-progress-bar-percent'),
																						progressBarPercent = progressBarsCountUpItem.attr('data-progress-percent');

																				// progress bar fill animation
																				progressBarsFillItem.animate({
																					width: progressBarPercent + '%'
																				}, duration, 'swing');

																				// find amount of numbers after the decimal point
																				var numbersAfterComma = 0;

																				if (progressBarPercent.indexOf('.') > 0) {
																					numbersAfterComma = progressBarPercent.length - (progressBarPercent.indexOf('.') + 1);
																				}

																				// count up animation
																				var options = {
																					useEasing: false,
																					decimal: '.',
																					decimalPlaces: numbersAfterComma,
																					duration: duration/1000,
																					suffix: '%'
																				};

																				new countUp.CountUp(progressBarsCountUpItem.get(0), progressBarPercent, options).start();
																			});
																		}

																		function progressBarsOnScroll() {
																			var progressBarsBlock = $('.js-progress-bars');

																			if (progressBarsBlock.length) {
																				progressBarsBlock.waypoint({
																					handler: function() {
																						if (!this.element.progressBarsInit) {
																							this.element.progressBarsInit = true;

																							progressBars(this.element, 4000);
																						}
																					},
																					offset: '80%'
																				})
																			}
																		}

																		progressBarsOnScroll();
																	}

																	initProgressBars();
																
															

Shuffle filter HTML SASS JS

Simple and beautiful filtration of items based on shuffle.js. In example for a grid is used Bootstrap.

Red

Green

Blue

Green

Blue

Red

This component is dependent on shuffle.js.

In order to support browsers like IE11 and Safari 8, you must include a babel-polyfil before all your compiled Babel code. Polyfill you can get here.

														
															<script src="/path/to/polyfill.min.js"></script>
															<script src="/path/to/shuffle.min.js"></script>
															<script src="/path/to/common.js"></script>
														
													
																
																	// STYLES FOR AN EXAMPLE - REMOVE/EDIT AFTER COPYING

																	.filter-nav {
																		text-align: center;
																		margin-bottom: 30px;

																		&__item {
																			display: inline-block;
																			margin: 0 10px;
																		}

																		&__link {
																			font-size: 1.25rem;
																			font-weight: 700;
																			color: #25253E;
																			opacity: 0.5;

																			&.-active {
																				opacity: 1;
																			}
																		}
																	}

																	.filter-item {
																		height: 150px;
																		border-radius: 5px;
																		display: -webkit-flex;
																		display: -moz-flex;
																		display: -ms-flex;
																		display: -o-flex;
																		display: flex;
																		align-items: center;
																		justify-content: center;
																		font-size: 20px;
																		color: #fff;
																		margin-bottom: 1rem;

																		p {
																			margin-bottom: 0;
																		}

																		&.-red {
																			background-color: #d04343;
																		}

																		&.-green {
																			background-color: #48a748;
																		}

																		&.-blue {
																			background-color: #3b46bd;
																		}
																	}
																
															
																
																	// SHUFFLE FILTER
																	function initFilter() {
																		var filterContainer = $('.js-filter-container');

																		if (filterContainer.length) {
																			var filterContent = filterContainer.find('.filter-content'),
																					filterNav = filterContainer.find('.filter-nav'),
																					filterCategoryName = '',
																					shuffle = window.shuffle;

																			var myShuffle = new Shuffle(filterContent, {
																				speed: 400,
																				easing: 'ease',
																			});

																			myShuffle.update();

																			// filtering by click
																			filterNav.find('a').on('click', function() {

																				filterNav.find('a').removeClass('-active');
																				$(this).addClass('-active');
																				filterCategoryName = $(this).attr('data-group');

																				myShuffle.filter(filterCategoryName, shuffle);

																				myShuffle.update();

																			});
																		}
																	}

																	initFilter();
																
															

Active header after scroll JS

Adding class="-active" after the start of scrolling and removing it, when you are at the top of the page. With this class you can make the header smaller or fill it with color.

																
																	.header {
																		&.-active {
																			// small header styles
																		}
																	}
																
															
																
																	// ACTIVE HEADER AFTER SCROLL
																	function initActiveHeaderAfterScroll() {
																		var header = $('.js-header');

																		$(window).on('scroll', function() {
																			if ($(this).scrollTop() > 10) {
																				header.addClass('-active');
																			} else {
																				header.removeClass('-active');
																			}
																		});

																		if ($(document).scrollTop() > 10) {
																			header.addClass('-active');
																		}
																	}

																	initActiveHeaderAfterScroll();
																
															

Scroll top button HTML SASS JS

Simple button for scrolling to top of the page. Button is hide, when you are in the top of page, and visible when you start scrolling.

For icon were used Font Awesome 5.

																
																	$scroll-top-btn-size: 50px;
																	$scroll-top-btn-bg: #26263F;

																	.scroll-top-btn {
																		position: fixed;
																		bottom: 0;
																		right: 50px;
																		z-index: 101;
																		width: $scroll-top-btn-size;
																		height: $scroll-top-btn-size;
																		border: none;
																		cursor: pointer;
																		background-color: $scroll-top-btn-bg;
																		transition: 0.3s;
																		transform: translate(0, 100%);

																		&__icon {
																			font-size: 35px;
																			color: #fff;
																			position: absolute;
																			top: 50%;
																			left: 50%;
																			transform: translate(-50%, -50%);
																		}

																		&:hover {
																			background-color: lighten($scroll-top-btn-bg, 5%);
																		}

																		&.-show {
																			transform: translate(0, 0);
																		}
																	}
																
															
																
																	function initScrollTopBtn() {
																		function showHideScrollTopBtn(distance) {
																			var scrollTopBtn = $('.js-scroll-top-btn');

																			$(window).on('scroll', function() {
																				if ($(this).scrollTop() > distance) {
																					scrollTopBtn.addClass('-show');
																				} else {
																					scrollTopBtn.removeClass('-show');
																				}
																			});

																			if ($(document).scrollTop() > distance) scrollTopBtn.addClass('-show');
																		}

																		function scrollTopAnimation() {
																			var scrollTopBtn = $('.js-scroll-top-btn'),
																					scrollingComplete = true;

																			scrollTopBtn.on('click', function() {

																				if (scrollingComplete) {
																					scrollingComplete = false;

																					$('body, html').animate({
																						scrollTop: 0
																					}, 1000 ).promise().done(function() {
																						scrollingComplete = true;
																					});

																					return false;
																				}
																			});
																		}

																		function scrollTopBtn() {
																			// 1) checking the distance from the top of the page
																			showHideScrollTopBtn(100);
																			// 2) сlick event to scroll top
																			scrollTopAnimation();
																		}

																		scrollTopBtn();
																	}

																	initScrollTopBtn();
																
															

Width of scrollbar JS

Cross-browser method of getting scroll bar width via JavaScript. This can be useful, for example, when you open pop-up, and turn off the page scrolling (scrollbar disappears and happening jump of the page). In this case, you will need to compensate the width of the scrollbar.

														
															// WIDTH OF SCROLLBAR
															function getScrollBarWidth() {
																if (window.innerWidth > $(window).width()) {
																	var $outer = $('<div>').css({visibility: 'hidden', width: 100, overflow: 'scroll'}).appendTo('body'),
																			widthWithScroll = $('<div>').css({width: '100%'}).appendTo($outer).outerWidth();
																	$outer.remove();
																	window.widthOfScrollbar = 100 - widthWithScroll;
																	return 100 - widthWithScroll;
																} else {
																	return window.widthOfScrollbar = 0;
																}
															}

															getScrollBarWidth();

															$(window).on('resize', function() {
																getScrollBarWidth();
															});

															function addScrollbarCompensation(element) {
																element.css('padding-right', window.widthOfScrollbar);
															}

															function removeScrollbarCompensation(element) {
																element.css('padding-right', 0);
															}

															// example
															addScrollbarCompensation($('.element-one, .element-two'));

															removeScrollbarCompensation($('.element-one, .element-two'));
														
													

Custom checkbox and radio button HTML SASS

Creation and customize custom сheckboxs and radio buttons only using HTML and CSS.

Checkbox:
Radio button:

For icon were used Font Awesome 5.

																
																	// CUSTOM CHECKBOX

																	$checkbox-checkmark-size: 25px;
																	$checkbox-bg-color: #4C4E6C;

																	// states
																	$checkbox-checked-bg-color: #26263F;
																	$checkbox-disabled-bg-color: #a2a3b4;
																	$checkbox-focus-box-shadow-color: #c0c774;

																	.custom-checkbox {
																		position: relative;
																		padding-left: 35px;
																		margin-bottom: 15px;
																		line-height: $checkbox-checkmark-size;
																		cursor: pointer;

																		&__checkmark {
																			position: absolute;
																			top: 50%;
																			left: 0;
																			transform: translate(0, -50%);
																			width: $checkbox-checkmark-size;
																			height: $checkbox-checkmark-size;
																			background-color: $checkbox-bg-color;
																			box-shadow: 0 0 0 0 $checkbox-focus-box-shadow-color;
																			transition: background-color 0.3s, box-shadow 0.3s;
																		}

																		&__icon {
																			position: absolute;
																			top: 50%;
																			left: 50%;
																			transform: translate(-50%, -50%);
																			display: inline-block;
																			font-size: 15px;
																			color: #fff;
																			opacity: 0;
																			transition: opacity 0.2s;
																		}

																		&__input {
																			position: absolute;
																			width: 1px;
																			height: 1px;
																			margin: -1px;
																			padding: 0;
																			border: 0;
																			clip: rect(0 0 0 0);
																			overflow: hidden;

																			// checked styles
																			&:checked + {
																				.custom-checkbox__checkmark {
																					background-color: $checkbox-checked-bg-color;

																					.custom-checkbox__icon {
																						opacity: 1;
																					}
																				}
																			}

																			// disabled styles
																			&:disabled + {
																				.custom-checkbox__checkmark {
																					background-color: $checkbox-disabled-bg-color;
																				}
																			}

																			// focus styles
																			&:focus + {
																				.custom-checkbox__checkmark {
																					box-shadow: 0 0 0 3px $checkbox-focus-box-shadow-color;
																				}
																			}
																		}

																		&:hover {
																			.custom-checkbox__input:not(:disabled):not(:checked) + {
																				.custom-checkbox__checkmark {
																					background-color: lighten($checkbox-bg-color, 10%);
																				}
																			}
																		}
																	}
																
															
																
																	// CUSTOM RADIO

																	$radio-checkmark-size: 25px;
																	$radio-bg-color: #4C4E6C;

																	// states
																	$radio-checked-bg-color: #26263F;
																	$radio-disabled-bg-color: #a2a3b4;
																	$radio-focus-box-shadow-color: #c0c774;

																	.custom-radio {
																		position: relative;
																		padding-left: 35px;
																		margin-bottom: 15px;
																		line-height: $radio-checkmark-size;
																		cursor: pointer;

																		&__checkmark {
																			position: absolute;
																			top: 50%;
																			left: 0;
																			transform: translate(0, -50%);
																			width: $radio-checkmark-size;
																			height: $radio-checkmark-size;
																			border-radius: 50%;
																			background-color: $radio-bg-color;
																			box-shadow: 0 0 0 0 $checkbox-focus-box-shadow-color;
																			transition: background-color 0.3s, box-shadow 0.3s;
																		}

																		&__icon {
																			position: absolute;
																			top: 50%;
																			left: 50%;
																			transform: translate(-50%, -50%);
																			display: inline-block;
																			font-size: 9px;
																			color: #ffffff;
																			transition: opacity 0.2s;
																			opacity: 0;
																		}

																		&__input {
																			position: absolute;
																			width: 1px;
																			height: 1px;
																			margin: -1px;
																			padding: 0;
																			border: 0;
																			clip: rect(0 0 0 0);
																			overflow: hidden;

																			// checked styles
																			&:checked + {
																				.custom-radio__checkmark {
																					background-color: $radio-checked-bg-color;

																					.custom-radio__icon {
																						opacity: 1;
																					}
																				}
																			}

																			// disabled styles
																			&:disabled + {
																				.custom-radio__checkmark {
																					background-color: $radio-disabled-bg-color;
																				}
																			}

																			// focus styles
																			&:focus + {
																				.custom-radio__checkmark {
																					box-shadow: 0 0 0 3px $checkbox-focus-box-shadow-color;
																				}
																			}
																		}

																		&:hover {
																			.custom-radio__input:not(:disabled):not(:checked) + {
																				.custom-radio__checkmark {
																					background-color: lighten($radio-bg-color, 10%);
																				}
																			}
																		}
																	}
																
															

Google map HTML SASS JS

Embed a Google Map on site. The following settings for google map are also prepared in advance: styles for theme, custom icon (png or svg), info window and others.

For map with multiple markers zoom are calculated automatically based on the distance of the markers from each other.

Add class="-map-absolute" to make the map stretched across his parent's area.

Standart map:
Multiple markers:

First of all insert a script that loads the API from the specified URL.

After key= insert your API key, which you can get here.

														
															<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
														
													
																
																	.google-map {
																		height: 300px;
																		background-color: #26263F;

																		// hide bottom labels
																		.gm-style-cc {
																			display: none;
																		}

																		// hide google label
																		a[href^="http://maps.google.com/maps"],
																		a[href^="https://maps.google.com/maps"],
																		a[href^="https://www.google.com/maps"] {
																			display: none !important;
																		}
																	}
																
															
																
																	// STANDARD GOOGLE MAP
																	function initMap() {
																		var mapBlock = $('.js-map');

																		if (!mapBlock.length) return;

																		var coordinateX = mapBlock.attr('data-coordinate-x'),
																				coordinateY = mapBlock.attr('data-coordinate-y'),
																				coordinates = new google.maps.LatLng(coordinateX, coordinateY);

																		var map = new google.maps.Map(mapBlock.get(0), {
																			center: coordinates,
																			zoom: 12,
																			disableDefaultUI: true,
																			zoomControl: true,
																			fullscreenControl: true,
																			zoomControlOptions: {
																				position: google.maps.ControlPosition.RIGHT_CENTER
																			},

																			// OPTIONAL - styles for theme (https://snazzymaps.com)
																			// minify code (https://www.minifier.org)

																			// styles: [{"featureType":"administrative","elementType":"all","stylers":[{"saturation":"-100"}]},{"featureType":"administrative.province","elementType":"all","stylers":[{"visibility":"off"}]},{"featureType":"landscape","elementType":"all","stylers":[{"saturation":-100},{"lightness":65},{"visibility":"on"}]},{"featureType":"poi","elementType":"all","stylers":[{"saturation":-100},{"lightness":"50"},{"visibility":"simplified"}]},{"featureType":"road","elementType":"all","stylers":[{"saturation":"-100"}]},{"featureType":"road.highway","elementType":"all","stylers":[{"visibility":"simplified"}]},{"featureType":"road.arterial","elementType":"all","stylers":[{"lightness":"30"}]},{"featureType":"road.local","elementType":"all","stylers":[{"lightness":"40"}]},{"featureType":"transit","elementType":"all","stylers":[{"saturation":-100},{"visibility":"simplified"}]},{"featureType":"water","elementType":"geometry","stylers":[{"hue":"#ffff00"},{"lightness":-25},{"saturation":-97}]},{"featureType":"water","elementType":"labels","stylers":[{"lightness":-25},{"saturation":-100}]}]
																		});

																		// OPTIONAL - custom icon
																		var icon = {
																			url: '../img/svg/icon_map_marker.svg',
																			scaledSize: new google.maps.Size(50, 50)
																		};

																		var marker = new google.maps.Marker({
																			position: coordinates,
																			map: map,

																			// OPTIONAL - animation of marker
																			// animation: google.maps.Animation.BOUNCE,

																			// OPTIONAL - text on marker hover
																			// title: 'text on hover',

																			// OPTIONAL - custom icon from png or svg
																			// icon: icon
																		});

																		// OPTIONAL - add info window
																		var infoWindow = new google.maps.InfoWindow({
																			content: '<p>Info window</p>'
																		});

																		// show info window after click
																		/*marker.addListener('click', function() {
																			infoWindow.open(map, marker);
																		});*/

																		// show info window all time
																		/*google.maps.event.addListenerOnce(map, 'tilesloaded', function() {
																			infoWindow.open(map,marker);
																		});*/

																		// close info window after click anywhere on the map
																		google.maps.event.addListener(map, 'click', function() {
																			infoWindow.close();
																		});
																	}

																	initMap();
																
															
																
																	// GOOGLE MAP WITH MULTIPLE MARKER
																	function initMapMultipleMarkers() {
																		var mapBlock = $('.js-map-multiple-markers');

																		if (!mapBlock.length) return;

																		var map = new google.maps.Map(mapBlock.get(0), {
																			disableDefaultUI: true,
																			zoomControl: true,
																			fullscreenControl: true,
																			zoomControlOptions: {
																				position: google.maps.ControlPosition.RIGHT_CENTER
																			}
																		});

																		// array of markers (with coordinates, name, address)
																		var multipleMarkers = [
																			{
																				lat: 40.679680,
																				lng: -73.942175,
																				name: 'Name 1',
																				address: 'Address 1'
																			},
																			{
																				lat: 40.729391,
																				lng: -74.076758,
																				name: 'Name 2',
																				address: 'Address 2'
																			},
																			{
																				lat: 40.745260,
																				lng: -73.997794,
																				name: 'Name 3',
																				address: 'Address 3'
																			}
																		];

																		var infoWindow = new google.maps.InfoWindow();

																		google.maps.event.addListener(map, 'click', function() {
																			infoWindow.close();
																		});

																		// Determine the boundaries of the visible area of the map in accordance with the position of the markers
																		var bounds = new google.maps.LatLngBounds();

																		// create the markers
																		for (var i = 0; i < multipleMarkers.length; i++){

																			var latLng = new google.maps.LatLng(multipleMarkers[i].lat, multipleMarkers[i].lng);
																			var name = multipleMarkers[i].name;
																			var address = multipleMarkers[i].address;

																			addMarker(latLng, name, address);

																			// Expand the boundaries of our visible area by adding the coordinates of our current marker
																			bounds.extend(latLng);
																		}

																		// Automatically scale the map so that all markers are in the visible area of the map
																		map.fitBounds(bounds);

																		function addMarker(latLng, name, address) {
																			var marker = new google.maps.Marker({
																				position: latLng,
																				map: map,
																				title: name
																			});

																			google.maps.event.addListener(marker, 'click', function() {
																				var contentString = '<div class="infowindow">' +
																															'<h5>' + name + '</h5>' +
																															'<p>' + address + '</p>' +
																														'</div>';

																				infoWindow.setContent(contentString);
																				infoWindow.open(map, marker);
																			});
																		}
																	}

																	initMapMultipleMarkers();
																
															

HTML map marker HTML SASS JS

Adding to Google Map custom HTML-marker which can be stylized how do you want.
																
																	// PULSE ANIMATION

																	$marker-color: #fff;
																	$marker-dot-width: 8px;
																	$marker-dot-height: $marker-dot-width;
																	$marker-end-size: 120px;
																	$animation-duration: 2.5s;

																	@mixin markerEndSize($circleEndSize){
																		width: $circleEndSize;
																		height: $circleEndSize;
																	}

																	.html-map-marker {
																		position: absolute;
																		z-index: 100;
																		width: $marker-dot-width;
																		height: $marker-dot-height;
																		background-color: $marker-color;
																		border-radius: 50%;

																		&:before,
																		&:after {
																			content: '';
																			background-color: rgba($marker-color, 1);
																			position: absolute;
																			top: 50%;
																			left: 50%;
																			transform: translate(-50%, -50%);
																			border-radius: 50%;
																			transform-origin: center center;
																			animation: pulse $animation-duration linear infinite;
																		}

																		&:after {
																			animation-delay: $animation-duration/2;
																		}
																	}

																	@keyframes pulse {
																		0% {
																			@include markerEndSize(0);
																			background-color: rgba($marker-color, 0);
																		}
																		50% {
																			background-color: rgba($marker-color, 0.2);
																		}
																		70% {
																			background-color: rgba($marker-color, 0.4);
																		}
																		100% {
																			@include markerEndSize($marker-end-size);
																			background-color: rgba($marker-color, 0);
																		}
																	}
																
															
																
																	// MAP WITH HTML MARKER
																	function initMapWithHtmlMarker() {
																		var mapBlock = $('.js-map-with-marker');

																		if (!mapBlock.length) return;

																		var coordinateX = mapBlock.attr('data-coordinate-x'),
																				coordinateY = mapBlock.attr('data-coordinate-y'),
																				coordinates = new google.maps.LatLng(coordinateX, coordinateY);

																		var map = new google.maps.Map(mapBlock.get(0), {
																			center: coordinates,
																			zoom: 12,
																			disableDefaultUI: true,
																			zoomControl: false,
																			fullscreenControl: false,
																			styles: [{"featureType":"all","elementType":"labels.text.fill","stylers":[{"saturation":36},{"color":"#000000"},{"lightness":40}]},{"featureType":"all","elementType":"labels.text.stroke","stylers":[{"visibility":"on"},{"color":"#000000"},{"lightness":16}]},{"featureType":"all","elementType":"labels.icon","stylers":[{"visibility":"off"}]},{"featureType":"administrative","elementType":"geometry.fill","stylers":[{"color":"#000000"},{"lightness":20}]},{"featureType":"administrative","elementType":"geometry.stroke","stylers":[{"color":"#000000"},{"lightness":17},{"weight":1.2}]},{"featureType":"landscape","elementType":"geometry","stylers":[{"color":"#000000"},{"lightness":20}]},{"featureType":"poi","elementType":"geometry","stylers":[{"color":"#000000"},{"lightness":21}]},{"featureType":"road.highway","elementType":"geometry.fill","stylers":[{"color":"#000000"},{"lightness":17}]},{"featureType":"road.highway","elementType":"geometry.stroke","stylers":[{"color":"#000000"},{"lightness":29},{"weight":0.2}]},{"featureType":"road.arterial","elementType":"geometry","stylers":[{"color":"#000000"},{"lightness":18}]},{"featureType":"road.local","elementType":"geometry","stylers":[{"color":"#000000"},{"lightness":16}]},{"featureType":"transit","elementType":"geometry","stylers":[{"color":"#000000"},{"lightness":19}]},{"featureType":"water","elementType":"geometry","stylers":[{"color":"#000000"},{"lightness":17}]}]
																		});

																		// HTML MAP MARKER
																		function CustomMarker(latlng, map, args) {
																			this.latlng = latlng;
																			this.args = args;
																			this.setMap(map);
																		}

																		CustomMarker.prototype = new google.maps.OverlayView();

																		CustomMarker.prototype.draw = function() {

																			var self = this;

																			var div = this.div;

																			if (!div) {

																				div = this.div = document.createElement('div');

																				div.className = 'html-map-marker';

																				if (typeof(self.args.marker_id) !== 'undefined') {
																					div.dataset.marker_id = self.args.marker_id;
																				}

																				google.maps.event.addDomListener(div, "click", function(event) {
																					// marker click
																					google.maps.event.trigger(self, "click");
																				});

																				var panes = this.getPanes();
																				panes.overlayImage.appendChild(div);
																			}

																			var point = this.getProjection().fromLatLngToDivPixel(this.latlng);

																			var mapMarkerWidth = $('.html-map-marker').width() / 2;

																			if (point) {
																				div.style.left = (point.x - mapMarkerWidth) + 'px';
																				div.style.top = (point.y - mapMarkerWidth) + 'px';
																			}
																		};

																		CustomMarker.prototype.remove = function() {
																			if (this.div) {
																				this.div.parentNode.removeChild(this.div);
																				this.div = null;
																			}
																		};

																		CustomMarker.prototype.getPosition = function() {
																			return this.latlng;
																		};

																		var overlay = new CustomMarker(
																			coordinates,
																			map,
																			{
																				marker_id: 'html-map-murker'
																			}
																		);
																		// HTML MAP MARKER END
																	}

																	initMapWithHtmlMarker();
																
															

Embed responsive video HTML SASS

Embed a YouTube or Vimeo video on web-site and make it responsive. You can set aspect ratios by modifier classes: class="-ratio-16-9" or class="-ratio-4-3" or class="-ratio-1-1".

Ratio 16 x 9:
Ratio 4 x 3:
Ratio 1 x 1:

Do not forget to insert your VIDEO_ID to iframe.

																
																	.responsive-video {
																		position: relative;

																		&__item {
																			position: absolute;
																			top: 0;
																			bottom: 0;
																			left: 0;
																			right: 0;
																			z-index: 1;
																			width: 100%;
																			height: 100%;
																			border: 0;
																		}

																		&.-ratio-16-9 {
																			padding-bottom: 56.25%;
																		}

																		&.-ratio-4-3 {
																			padding-bottom: 75%;
																		}

																		&.-ratio-1-1 {
																			padding-bottom: 100%;
																		}
																	}
																
															

Youtube thumbnail HTML SASS JS

Making YouTube thumbnails based on iframe. At the beginning - we show thumbnail, and hide iframe. After click - hide thumbnail and show iframe (with autoplay attribute). By this method the page is loaded without iframes which speeds up the loading of the site.

Do not forget to insert your VIDEO_ID to iframe.

																
																	.youtube-thumbnail {
																		position: relative;
																		cursor: pointer;
																		padding-bottom: 56.25%;
																		background-color: #000000;

																		&__media {
																			position: absolute;
																			right: 0;
																			left: 0;
																			width: 100%;
																			height: 100%;
																			z-index: 1;

																			&.-bg-image {
																				background-size: cover;
																				background-position: center;
																				background-repeat: no-repeat;
																			}

																			&:hover {
																				.youtube-icon__figure {
																					transition: fill .1s cubic-bezier(0.0,0.0,0.2,1),fill-opacity .1s cubic-bezier(0.0,0.0,0.2,1);
																					fill: #f00;
																					fill-opacity: 1;
																				}
																			}
																		}

																		&__icon {
																			position: absolute;
																			top: 50%;
																			left: 50%;
																			transform: translate(-50%, -50%);
																		}
																	}

																	.youtube-icon {
																		width: 68px;
																		height: 48px;

																		&__figure {
																			transition: fill .1s cubic-bezier(0.4,0.0,1,1),fill-opacity .1s cubic-bezier(0.4,0.0,1,1);
																		}
																	}
																
															
																
																	// YOUTUBE THUMBNAIL
																	function initYouTubeThumbnail() {
																		function getYouTubeVideoId(videoItem) {
																			var videoThumbnailUrl = videoItem.find('.js-youtube-thumbnail-media').attr('style');

																			return videoThumbnailUrl.split('/')[videoThumbnailUrl.split('/').length - 2];
																		}

																		function insertYouTubeIframe() {
																			$('.js-youtube-thumbnail').on('click', function() {
																				var youTubeIframe = $('<iframe class="youtube-thumbnail__media" allowfullscreen></iframe>');
																						youTubeIframe.attr('allow', 'autoplay');
																						youTubeIframe.attr('src', 'https://www.youtube.com/embed/' + getYouTubeVideoId($(this)) + '?rel=0&showinfo=0&autoplay=1');

																				$(this).find('.js-youtube-thumbnail-media').remove();
																				$(this).append(youTubeIframe);
																			})
																		}

																		insertYouTubeIframe();
																	}

																	initYouTubeThumbnail();
																
															

Vimeo thumbnail HTML SASS JS

Making Vimeo thumbnails based on iframe. At the beginning - we show thumbnail, and hide iframe. After click - hide thumbnail and show iframe (with autoplay attribute). By this method the page is loaded without iframes which speeds up the loading of the site.

Do not forget to insert your VIDEO_ID to iframe.

																
																	.vimeo-thumbnail {
																		position: relative;
																		cursor: pointer;
																		padding-bottom: 56.25%;
																		background-color: #000000;

																		&__media {
																			position: absolute;
																			right: 0;
																			left: 0;
																			width: 100%;
																			height: 100%;
																			z-index: 1;

																			&.-bg-image {
																				background-size: cover;
																				background-position: center;
																				background-repeat: no-repeat;
																			}

																			&:hover {
																				.vimeo-icon {
																					background-color: #3CAEF2;
																				}
																			}
																		}

																		&__icon {
																			position: absolute;
																			top: 50%;
																			left: 50%;
																			transform: translate(-50%, -50%);
																		}
																	}

																	.vimeo-icon {
																		width: 65px;
																		height: 40px;
																		transition: opacity 250ms ease-out,background-color 40ms,color 40ms;
																		background: rgba(23,35,34,.75);
																		border-radius: .5em;

																		&__icon {
																			position: absolute;
																			top: 50%;
																			left: 50%;
																			transform: translate(-50%, -50%);
																			width: 20px;
																			height: 20px;
																		}
																	}
																
															
																
																	// VIMEO THUMBNAIL
																	function initVimeoThumbnail() {
																		function getVimeoVideoId(vimeoBlock) {
																			return vimeoBlock.attr('data-vimeo-url').split('/').pop();
																		}

																		function setVimeoThumbnailBackground(vimeoBlock) {
																			$.getJSON('https://vimeo.com/api/v2/video/' + getVimeoVideoId(vimeoBlock) + '.json', function (data) {
																				var thumbnailImg = data[0].thumbnail_large;

																				vimeoBlock.find('.js-vimeo-thumbnail-media').css('background-image', 'url(' + thumbnailImg + ')');
																			});
																		}

																		function setVimeoThumbnailBackgroundToAllBlocks() {
																			$('.js-vimeo-thumbnail').each(function() {
																				setVimeoThumbnailBackground($(this));
																			});
																		}

																		setVimeoThumbnailBackgroundToAllBlocks();

																		function insertVimeoIframe() {
																			$('.js-vimeo-thumbnail').on('click', function() {
																				var vimeoIframe = $('<iframe class="vimeo-thumbnail__media" allowfullscreen></iframe>');
																						vimeoIframe.attr('allow', 'autoplay');
																						vimeoIframe.attr('src', 'https://player.vimeo.com/video/' + getVimeoVideoId($(this)) + '?autoplay=1');

																				$(this).find('.js-vimeo-thumbnail-media').remove();
																				$(this).append(vimeoIframe);
																			})
																		}

																		insertVimeoIframe();
																	}

																	initVimeoThumbnail();
																
															

Background video HTML SASS JS

Background video for the block. May be useful for background video for a section.

This component is dependent on jquery-background-video.

																
																	.bg-video-block {
																		position: relative;
																		height: 300px;

																		&__html-bg-video {
																			position: absolute;
																			min-width: 100%;
																			min-height: 100%;
																			width: auto;
																			height: auto;
																			top: 50%;
																			left: 50%;
																			object-fit: cover;
																			transform: translate(-50%,-50%);
																			opacity: 0;
																			transition: opacity 300ms linear;

																			&.is-visible {
																				opacity: 1;
																			}
																		}
																	}
																
															
																
																	function initBackgroundVideo() {
																		if ($('.js-html-bg-video').length) {
																			$('.js-html-bg-video').bgVideo({
																				showPausePlay: false,
																				pauseAfter: 0
																			});
																		}
																	}

																	initBackgroundVideo();