├── src ├── img │ └── .gitkeep ├── templates │ ├── partials │ │ └── partial.twig │ ├── components │ │ ├── component.twig │ │ └── navbar.twig │ ├── page.twig │ ├── layouts │ │ └── default.twig │ ├── demo.twig │ └── index.twig ├── robots.txt ├── js │ ├── main.js │ ├── vendor │ │ ├── windowwidth.js │ │ ├── plugins.js │ │ ├── smartresize.js │ │ └── smoothscrolling.js │ └── components │ │ └── navbar.js └── sass │ ├── main.scss │ ├── _variables.scss │ ├── base │ ├── _minireset.scss │ ├── _print.scss │ └── _mixins.scss │ ├── _typography.scss │ ├── components │ ├── _buttons.scss │ └── _navbar.scss │ └── vendor │ ├── _bootstrap.scss │ └── _normalize.scss ├── .gitignore ├── LICENSE.md ├── package.json ├── README.md └── gulpfile.js /src/img/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/templates/partials/partial.twig: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/templates/components/component.twig: -------------------------------------------------------------------------------- 1 | {% if foo is defined %} 2 | foo: {{ foo }} 3 | {% endif %} 4 | -------------------------------------------------------------------------------- /src/robots.txt: -------------------------------------------------------------------------------- 1 | # www.robotstxt.org/ 2 | 3 | # Allow crawling of all content 4 | User-agent: * 5 | Disallow: 6 | -------------------------------------------------------------------------------- /src/js/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Main 3 | * Custom Scripts 4 | */ 5 | 6 | $(function() { 7 | // Document Ready 8 | }) 9 | 10 | $(window).smartresize(function() { 11 | // Debouncing function from John Hann 12 | // http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/ 13 | }); 14 | -------------------------------------------------------------------------------- /src/templates/page.twig: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/default.twig' %} 2 | {% set head_title = 'Sample Page' %} 3 | {% set body_class = '' %} 4 | {% set menu_active = 'sample-page' %} 5 | 6 | {% block page %} 7 | 8 | {% include 'components/navbar.twig' %} 9 | 10 |
11 |

12 | Hello World 13 |

14 |
15 | 16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependency directories 2 | node_modules 3 | bower_components 4 | dist 5 | 6 | # Optional npm cache directory 7 | .npm 8 | 9 | # SASS Cache 10 | .sass-cache 11 | .sass-cache/* 12 | 13 | # Logs 14 | logs 15 | *.log 16 | npm-debug.log* 17 | 18 | # OSX 19 | *.DS_Store 20 | .AppleDouble 21 | .LSOverride 22 | 23 | # Windows 24 | Thumbs.db 25 | ehthumbs.db 26 | 27 | # Misc 28 | .publish 29 | -------------------------------------------------------------------------------- /src/sass/main.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Project: Project name 3 | * Author: Author name 4 | */ 5 | 6 | // Vendor 7 | @import "vendor/bootstrap"; 8 | @import 'vendor/normalize'; 9 | 10 | // Base 11 | @import 'base/print'; 12 | @import 'base/mixins'; 13 | @import 'base/minireset'; 14 | 15 | // Variables 16 | @import 'variables'; 17 | 18 | // Typography 19 | @import 'typography'; 20 | 21 | // Components 22 | @import 'components/**/*.scss'; 23 | 24 | /** 25 | * Custom styles 26 | */ 27 | -------------------------------------------------------------------------------- /src/js/vendor/windowwidth.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Check Document Window Width 3 | */ 4 | 5 | function checkWindowWidth() { 6 | if ($(window).width() < 576) { 7 | // XS 8 | } else if ($(window).width() < 768) { 9 | // SM and down 10 | } else if ($(window).width() < 992) { 11 | // MD and down 12 | } else if ($(window).width() < 1200) { 13 | // LG and down 14 | } else { 15 | // XL and up 16 | } 17 | } 18 | 19 | $(function() { 20 | // checkWindowWidth(); 21 | }) 22 | 23 | $(window).smartresize(function() { 24 | // checkWindowWidth(); 25 | }); 26 | -------------------------------------------------------------------------------- /src/js/vendor/plugins.js: -------------------------------------------------------------------------------- 1 | // Avoid `console` errors in browsers that lack a console. 2 | (function() { 3 | var method; 4 | var noop = function () {}; 5 | var methods = [ 6 | 'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error', 7 | 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log', 8 | 'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd', 9 | 'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn' 10 | ]; 11 | var length = methods.length; 12 | var console = (window.console = window.console || {}); 13 | 14 | while (length--) { 15 | method = methods[length]; 16 | 17 | // Only stub undefined methods. 18 | if (!console[method]) { 19 | console[method] = noop; 20 | } 21 | } 22 | }()); 23 | 24 | // Place any jQuery/helper plugins in here. 25 | -------------------------------------------------------------------------------- /src/js/vendor/smartresize.js: -------------------------------------------------------------------------------- 1 | // debouncing function from John Hann 2 | // http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/ 3 | 4 | (function($,sr){ 5 | 6 | var debounce = function (func, threshold, execAsap) { 7 | var timeout; 8 | 9 | return function debounced () { 10 | var obj = this, args = arguments; 11 | function delayed () { 12 | if (!execAsap) 13 | func.apply(obj, args); 14 | timeout = null; 15 | }; 16 | 17 | if (timeout) 18 | clearTimeout(timeout); 19 | else if (execAsap) 20 | func.apply(obj, args); 21 | 22 | timeout = setTimeout(delayed, threshold || 100); 23 | }; 24 | } 25 | // smartresize 26 | jQuery.fn[sr] = function(fn){ return fn ? this.bind('resize', debounce(fn)) : this.trigger(sr); }; 27 | 28 | })(jQuery,'smartresize'); 29 | -------------------------------------------------------------------------------- /src/js/components/navbar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Navbar 3 | */ 4 | 5 | $(function() { 6 | 7 | // Navbar toggler 8 | var navbarToggler = $('.js-navbar-toggler'), 9 | navbarOpened = 'navbar--opened'; 10 | 11 | navbarToggler.on('click', function(e) { 12 | e.preventDefault(); 13 | $('body').toggleClass('navbar--opened'); 14 | }); 15 | 16 | /* 17 | Add class to navbar after certain amount of pixels are scrolled 18 | if navbar has class navbar-fixed-top then enable it 19 | e.g. when you want to provide some opacity to the background color 20 | */ 21 | var navbar = $('.js-navbar'), 22 | navbarScrolled = 'navbar--scrolled'; 23 | 24 | if (navbar.hasClass('navbar--fixed')) { 25 | $(window).scroll(function () { 26 | if ($(this).scrollTop() > 100) { 27 | navbar.addClass(navbarScrolled); 28 | } else { 29 | navbar.removeClass(navbarScrolled); 30 | } 31 | }); 32 | } 33 | 34 | }) 35 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) Frontie - Front-end HTML5 Boilerplate 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /src/templates/layouts/default.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ head_title }} · Frontie 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {% block page %}{% endblock %} 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/sass/_variables.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Variables 3 | */ 4 | 5 | // Colors 6 | $primary: #007bff; 7 | 8 | // Fonts 9 | $font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default; 10 | $font-size-base: 1rem; 11 | $line-height-base: 1.5; 12 | $body-color: #222; 13 | 14 | // Transition 15 | $transition-base: all .2s ease-in-out; 16 | 17 | /** 18 | * Typography Variables 19 | */ 20 | 21 | // Paragraph 22 | $paragraph-margin-bottom: 1rem; 23 | 24 | // Headings 25 | $headings-margin-bottom: 1rem; 26 | $headings-font-family: $font-family; 27 | $headings-font-weight: 500; 28 | $headings-line-height: inherit; 29 | $headings-color: inherit; 30 | 31 | // Headings Font Size 32 | $h1-font-size: $font-size-base * 2.5 !default; 33 | $h2-font-size: $font-size-base * 2 !default; 34 | $h3-font-size: $font-size-base * 1.75 !default; 35 | $h4-font-size: $font-size-base * 1.5 !default; 36 | $h5-font-size: $font-size-base * 1.25 !default; 37 | $h6-font-size: $font-size-base !default; 38 | 39 | // Links 40 | $link-color: #007bff; 41 | $link-decoration: none; 42 | $link-hover-color: darken($link-color, 15%); 43 | $link-hover-decoration: underline; 44 | -------------------------------------------------------------------------------- /src/sass/base/_minireset.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Reset, normalization of HTML elements 3 | */ 4 | 5 | *, 6 | *::before, 7 | *::after { 8 | box-sizing: border-box; // Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`. 9 | } 10 | 11 | html { 12 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 13 | } 14 | 15 | ol, 16 | ul, 17 | dl { 18 | margin-top: 0; 19 | margin-bottom: 1rem; 20 | } 21 | 22 | ol ol, 23 | ul ul, 24 | ol ul, 25 | ul ol { 26 | margin-bottom: 0; 27 | } 28 | 29 | figure { 30 | margin: 0; 31 | } 32 | 33 | img { 34 | vertical-align: middle; 35 | border-style: none; // Remove the border on images inside links in IE 10-. 36 | max-width: 100%; 37 | height: auto; 38 | } 39 | 40 | svg:not(:root) { 41 | overflow: hidden; // Hide the overflow in IE 42 | } 43 | 44 | input, 45 | button, 46 | select, 47 | optgroup, 48 | textarea { 49 | margin: 0; // Remove the margin in Firefox and Safari 50 | font-family: inherit; 51 | font-size: inherit; 52 | line-height: inherit; 53 | } 54 | 55 | button, 56 | input { 57 | overflow: visible; // Show the overflow in Edge 58 | } 59 | 60 | button, 61 | select { 62 | text-transform: none; // Remove the inheritance of text transform in Firefox 63 | } 64 | 65 | table { 66 | border-collapse: collapse; // Prevent double borders 67 | } 68 | -------------------------------------------------------------------------------- /src/sass/_typography.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Typography 3 | */ 4 | 5 | html { 6 | font-family: $font-family; 7 | font-size: $font-size-base; 8 | color: $body-color; 9 | line-height: $line-height-base; 10 | } 11 | 12 | p { 13 | margin-top: 0; 14 | margin-bottom: $paragraph-margin-bottom; 15 | } 16 | 17 | h1, 18 | h2, 19 | h3, 20 | h4, 21 | h5, 22 | h6, 23 | .h1, 24 | .h2, 25 | .h3, 26 | .h4, 27 | .h5, 28 | .h6 { 29 | margin-top: 0; 30 | margin-bottom: $headings-margin-bottom; 31 | font-family: $headings-font-family; 32 | font-weight: $headings-font-weight; 33 | line-height: $headings-line-height; 34 | color: $headings-color; 35 | } 36 | 37 | h1, 38 | .h1 { 39 | font-size: $h1-font-size; 40 | } 41 | h2, 42 | .h2 { 43 | font-size: $h2-font-size; 44 | } 45 | h3, 46 | .h3 { 47 | font-size: $h3-font-size; 48 | } 49 | h4, 50 | .h4 { 51 | font-size: $h4-font-size; 52 | } 53 | h5, 54 | .h5 { 55 | font-size: $h5-font-size; 56 | } 57 | h6, 58 | .h6 { 59 | font-size: $h6-font-size; 60 | } 61 | 62 | a { 63 | color: $link-color; 64 | text-decoration: $link-decoration; 65 | background-color: transparent; // Remove the gray background on active links in IE 10. 66 | -webkit-text-decoration-skip: objects; // Remove gaps in links underline in iOS 8+ and Safari 8+. 67 | &:hover { 68 | color: $link-hover-color; 69 | text-decoration: $link-hover-decoration; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/js/vendor/smoothscrolling.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Smooth Scrolling 3 | * https://css-tricks.com/snippets/jquery/smooth-scrolling/ 4 | */ 5 | 6 | // Select all links with hashes 7 | $('.is-scroll') 8 | // Remove links that don't actually link to anything 9 | .not('[href="#"]') 10 | .not('[href="#0"]') 11 | .click(function(event) { 12 | // On-page links 13 | if ( 14 | location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') 15 | && 16 | location.hostname == this.hostname 17 | ) { 18 | // Figure out element to scroll to 19 | var target = $(this.hash); 20 | target = target.length ? target : $('[name=' + this.hash.slice(1) + ']'); 21 | // Does a scroll target exist? 22 | if (target.length) { 23 | // Only prevent default if animation is actually gonna happen 24 | event.preventDefault(); 25 | $('html, body').animate({ 26 | scrollTop: target.offset().top 27 | }, 1000, function() { 28 | // Callback after animation 29 | // Must change focus! 30 | var $target = $(target); 31 | $target.focus(); 32 | if ($target.is(":focus")) { // Checking if the target was focused 33 | return false; 34 | } else { 35 | $target.attr('tabindex','-1'); // Adding tabindex for elements not focusable 36 | $target.focus(); // Set focus again 37 | }; 38 | }); 39 | } 40 | } 41 | }); 42 | -------------------------------------------------------------------------------- /src/templates/demo.twig: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/default.twig' %} 2 | {% set head_title = 'Components' %} 3 | {% set body_class = '' %} 4 | {% set menu_active = 'demo' %} 5 | 6 | {% block page %} 7 | 8 | {% include 'components/navbar.twig' %} 9 | 10 |
11 |
12 |
13 |

14 | Buttons 15 |

16 |

17 | Button 18 |

19 |

20 | Button Block 21 |

22 |

23 | Button Outline 24 |

25 |
26 |
27 |
28 | 29 |
30 |

31 | Scroll down to see fixed navbar feature 32 |

33 |
34 | 35 |
36 | 37 | Sample Twig features 38 | 39 | --- 40 | 41 | Let's loop over item in a sequence using twig "for" function 42 | 43 | {% for i in 0..3 %} 44 |

For Item: {{ i }}

45 | {% endfor %} 46 | 47 | --- 48 | 49 | Include component / partial 50 | 51 | {% include 'components/component.twig' %} 52 | 53 | {% include 'partials/partial.twig' %} 54 | 55 | --- 56 | 57 | Include component / partial with variable 58 | 59 | {% include 'components/component.twig' with {'foo': 'bar'} %} 60 | 61 |
62 | 63 | {% endblock %} 64 | -------------------------------------------------------------------------------- /src/sass/components/_buttons.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Buttons 3 | */ 4 | 5 | $btn-bg: $primary; 6 | $btn-text-color: white; 7 | $btn-font-weight: inherit; 8 | $btn-font-size: inherit; 9 | $btn-padding-x: .75rem; 10 | $btn-padding-y: .5rem; 11 | $btn-border-color: transparent; 12 | $btn-border-width: 1px; 13 | $btn-border-radius: 0; 14 | 15 | $btn-hover-bg: darken($primary, 10%); 16 | $btn-hover-text-color: white; 17 | $btn-hover-border-color: transparent; 18 | 19 | .btn { 20 | display: inline-block; 21 | padding: $btn-padding-y $btn-padding-x; 22 | border: $btn-border-width solid transparent; 23 | background-color: $btn-bg; 24 | color: $btn-text-color; 25 | vertical-align: middle; 26 | text-align: center; 27 | white-space: nowrap; 28 | font-size: $btn-font-size; 29 | font-weight: $btn-font-weight; 30 | cursor: pointer; 31 | transition: $transition-base; 32 | user-select: none; 33 | text-decoration: none; 34 | border-radius: $btn-border-radius; 35 | 36 | &:hover, 37 | &:focus { 38 | text-decoration: none; 39 | } 40 | 41 | &:focus { 42 | outline: 0; 43 | } 44 | 45 | &:hover { 46 | background-color: $btn-hover-bg; 47 | color: $btn-hover-text-color; 48 | border-color: $btn-hover-border-color; 49 | } 50 | } 51 | 52 | .btn-block { 53 | display: block; 54 | width: 100%; 55 | } 56 | 57 | .btn-outline { 58 | border: 1px solid $btn-bg; 59 | background-color: transparent; 60 | color: $btn-bg; 61 | &:hover { 62 | border-color: $btn-bg; 63 | background-color: $btn-bg; 64 | color: $btn-hover-text-color; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/sass/base/_print.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Print styles. 3 | * Taken from https://github.com/h5bp/html5-boilerplate 4 | */ 5 | 6 | /* ========================================================================== 7 | Print styles. 8 | Inlined to avoid the additional HTTP request: 9 | https://www.phpied.com/delay-loading-your-print-css/ 10 | ========================================================================== */ 11 | 12 | @media print { 13 | *, 14 | *:before, 15 | *:after { 16 | background: transparent !important; 17 | color: #000 !important; /* Black prints faster */ 18 | -webkit-box-shadow: none !important; 19 | box-shadow: none !important; 20 | text-shadow: none !important; 21 | } 22 | 23 | a, 24 | a:visited { 25 | text-decoration: underline; 26 | } 27 | 28 | a[href]:after { 29 | content: " (" attr(href) ")"; 30 | } 31 | 32 | abbr[title]:after { 33 | content: " (" attr(title) ")"; 34 | } 35 | 36 | /* 37 | * Don't show links that are fragment identifiers, 38 | * or use the `javascript:` pseudo protocol 39 | */ 40 | 41 | a[href^="#"]:after, 42 | a[href^="javascript:"]:after { 43 | content: ""; 44 | } 45 | 46 | pre { 47 | white-space: pre-wrap !important; 48 | } 49 | pre, 50 | blockquote { 51 | border: 1px solid #999; 52 | page-break-inside: avoid; 53 | } 54 | 55 | /* 56 | * Printing Tables: 57 | * http://css-discuss.incutio.com/wiki/Printing_Tables 58 | */ 59 | 60 | thead { 61 | display: table-header-group; 62 | } 63 | 64 | tr, 65 | img { 66 | page-break-inside: avoid; 67 | } 68 | 69 | p, 70 | h2, 71 | h3 { 72 | orphans: 3; 73 | widows: 3; 74 | } 75 | 76 | h2, 77 | h3 { 78 | page-break-after: avoid; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/templates/index.twig: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/default.twig' %} 2 | {% set head_title = 'Index' %} 3 | {% set body_class = 'index' %} 4 | 5 | {% block page %} 6 | 7 | 53 | 54 |
55 |

56 | Project Name 57 |

58 |

59 | This is the demo index page with basic styles for listing all of your pages. 60 |
61 | Tip: can be useful when showing the site preview to a client. 62 |

63 | 71 |
72 | 73 | {% endblock %} 74 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontie", 3 | "version": "1.1.0", 4 | "description": "Front-end Boilerplate. Frontie is a front-end boilerplate using Gulp for task automation. Based on normalize.css, Bootstrap 4 Grid & Responsive breakpoints and enhanced with Twig.js, Sass, Autoprefixer plus Browsersync.", 5 | "main": "gulpfile.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/tomaszbujnowicz/frontie.git" 12 | }, 13 | "keywords": [ 14 | "gulp", 15 | "frontend", 16 | "front-end boilerplate", 17 | "browsersync", 18 | "front-end development", 19 | "sass", 20 | "boilerplate", 21 | "bootstrap grid", 22 | "twig" 23 | ], 24 | "author": { 25 | "name": "Tomasz Bujnowicz", 26 | "email": "tomasz@prollective.com", 27 | "url": "https://prollective.com" 28 | }, 29 | "license": "MIT", 30 | "bugs": { 31 | "url": "https://github.com/tomaszbujnowicz/frontie/issues" 32 | }, 33 | "homepage": "https://github.com/tomaszbujnowicz/frontie#readme", 34 | "devDependencies": { 35 | "bootstrap": "^4.1.3", 36 | "browser-sync": "^2.26.3", 37 | "css-clean": "^2.2.5", 38 | "del": "^3.0.0", 39 | "gulp": "^3.9.1", 40 | "gulp-autoprefixer": "^6.0.0", 41 | "gulp-changed": "^3.2.0", 42 | "gulp-concat": "^2.6.1", 43 | "gulp-foreach": "^0.1.0", 44 | "gulp-gh-pages": "^0.5.4", 45 | "gulp-notify": "^3.2.0", 46 | "gulp-plumber": "^1.2.0", 47 | "gulp-sass": "^4.0.2", 48 | "gulp-sass-glob": "^1.0.9", 49 | "gulp-sass-lint": "^1.4.0", 50 | "gulp-sourcemaps": "^2.6.4", 51 | "gulp-twig": "^1.2.0", 52 | "gulp-uglify": "^3.0.1", 53 | "gulp-watch": "^5.0.1", 54 | "run-sequence": "^2.2.1" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/templates/components/navbar.twig: -------------------------------------------------------------------------------- 1 | {# 2 | .navbar--fixed 3 | If navbar shouldn't be fixed, 4 | remove the class "navbar--fixed" below and top padding from body {} in _navbar.scss 5 | CSS: /sass/components/_navbar.scss 6 | 7 | .js-navbar 8 | Navbar becomes automatically transparent when scrolling more than 100px down 9 | We add class "navbar--scrolled" to the "navbar", you can tweak opacity in _navbar.scss 10 | CSS: /sass/components/_navbar.scss 11 | JS: /js/components/navbar.js 12 | #} 13 | 14 | 51 | -------------------------------------------------------------------------------- /src/sass/vendor/_bootstrap.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Bootstrap 4.1.3 3 | * Via /node_modules + some modifications 4 | 5 | http://getbootstrap.com/docs/4.1/getting-started/theming/ 6 | Import bootstrap-grid.scss 7 | 8 | The only change comparing to the original structure is that we don't import whole "variables.scss" from Bootstrap. 9 | We don't all Bootstrap variagbles variables anyway. 10 | 11 | We comment // @import "variables"; and define Grids and Breakpoints variables directly here. 12 | */ 13 | 14 | /*! 15 | * Bootstrap Grid v4.1.3 (https://getbootstrap.com/) 16 | * Copyright 2011-2018 The Bootstrap Authors 17 | * Copyright 2011-2018 Twitter, Inc. 18 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 19 | */ 20 | 21 | @at-root { 22 | @-ms-viewport { width: device-width; } // stylelint-disable-line at-rule-no-vendor-prefix 23 | } 24 | 25 | html { 26 | box-sizing: border-box; 27 | -ms-overflow-style: scrollbar; 28 | } 29 | 30 | *, 31 | *::before, 32 | *::after { 33 | box-sizing: inherit; 34 | } 35 | 36 | @import "node_modules/bootstrap/scss/functions"; 37 | 38 | // @import "variables"; 39 | 40 | // Grid breakpoints 41 | // 42 | // Define the minimum dimensions at which your layout will change, 43 | // adapting to different screen sizes, for use in media queries. 44 | 45 | $grid-breakpoints: ( 46 | xs: 0, 47 | sm: 576px, 48 | md: 768px, 49 | lg: 992px, 50 | xl: 1200px 51 | ) !default; 52 | 53 | @include _assert-ascending($grid-breakpoints, "$grid-breakpoints"); 54 | @include _assert-starts-at-zero($grid-breakpoints); 55 | 56 | // Grid containers 57 | // 58 | // Define the maximum width of `.container` for different screen sizes. 59 | 60 | $container-max-widths: ( 61 | sm: 540px, 62 | md: 720px, 63 | lg: 960px, 64 | xl: 1140px 65 | ) !default; 66 | 67 | @include _assert-ascending($container-max-widths, "$container-max-widths"); 68 | 69 | // Grid columns 70 | // 71 | // Set the number of columns and specify the width of the gutters. 72 | 73 | $grid-columns: 12 !default; 74 | $grid-gutter-width: 30px !default; 75 | $enable-grid-classes: true !default; 76 | 77 | @import "node_modules/bootstrap/scss/mixins/breakpoints"; 78 | @import "node_modules/bootstrap/scss/mixins/grid-framework"; 79 | @import "node_modules/bootstrap/scss/mixins/grid"; 80 | 81 | @import "node_modules/bootstrap/scss/grid"; 82 | @import "node_modules/bootstrap/scss/utilities/display"; 83 | @import "node_modules/bootstrap/scss/utilities/flex"; 84 | 85 | /** 86 | * Demo: Bootstrap Media Queries 87 | * http://getbootstrap.com/docs/4.1/layout/overview/#responsive-breakpoints 88 | */ 89 | 90 | @include media-breakpoint-up(sm) {} 91 | @include media-breakpoint-up(md) {} 92 | @include media-breakpoint-up(lg) {} 93 | @include media-breakpoint-up(xl) {} 94 | 95 | @include media-breakpoint-down(xs) {} 96 | @include media-breakpoint-down(sm) {} 97 | @include media-breakpoint-down(md) {} 98 | @include media-breakpoint-down(lg) {} 99 | 100 | @include media-breakpoint-only(xs) {} 101 | @include media-breakpoint-only(sm) {} 102 | @include media-breakpoint-only(md) {} 103 | @include media-breakpoint-only(lg) {} 104 | @include media-breakpoint-only(xl) {} 105 | -------------------------------------------------------------------------------- /src/sass/components/_navbar.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Navbar 3 | */ 4 | 5 | $navbar-height-desktop: 80px; 6 | $navbar-height-mobile: 50px; 7 | $navbar-bg: #fafafa; 8 | $navbar-link-color: $primary; 9 | $navbar-hover-link-color: darken($primary, 15%); 10 | $z-index-navbar: 1000; 11 | $z-index-navbar-toggler: 1010; 12 | 13 | .navbar { 14 | 15 | background-color: $navbar-bg; 16 | z-index: $z-index-navbar; 17 | 18 | &__wrapper { 19 | display: flex; 20 | align-items: center; 21 | } 22 | &__brand { 23 | &:hover { 24 | text-decoration: none; 25 | } 26 | } 27 | &__toggler { 28 | display: none; 29 | background: none; 30 | border: none; 31 | border-radius: 0; 32 | &:focus { 33 | outline: none; 34 | } 35 | } 36 | &__menu { 37 | display: flex; 38 | list-style: none; 39 | margin: 0; 40 | padding: 0; 41 | } 42 | .menu-item { 43 | a { 44 | transition: $transition-base; 45 | color: $navbar-link-color; 46 | &:hover { 47 | color: $navbar-hover-link-color; 48 | text-decoration: none; 49 | } 50 | } 51 | } 52 | .current-menu-item { 53 | a { 54 | color: $navbar-hover-link-color; 55 | text-decoration: none; 56 | } 57 | } 58 | 59 | @include media-breakpoint-down(sm) { 60 | &__wrapper { 61 | height: $navbar-height-mobile; 62 | } 63 | &__collapse { 64 | transition: $transition-base; 65 | opacity: 0; 66 | visibility: hidden; 67 | position: fixed; 68 | top: 0; 69 | left: 0; 70 | right: 0; 71 | bottom: 0; 72 | width: 100%; 73 | height: 100%; 74 | overflow-x: hidden; 75 | overflow-y: auto; 76 | pointer-events: auto; 77 | } 78 | &__toggler { 79 | display: inline-block; 80 | position: relative; 81 | margin-left: auto; 82 | width: 40px; 83 | height: 32px; 84 | cursor: pointer; 85 | z-index: $z-index-navbar-toggler; 86 | } 87 | &__toggler-line { 88 | transition: $transition-base; 89 | display: block; 90 | position: absolute; 91 | top: 8px; 92 | left: 8px; 93 | background-color: black; 94 | height: 1px; 95 | width: 24px; 96 | &:nth-child(2) { 97 | top: 16px; 98 | } 99 | &:nth-child(3) { 100 | top: 24px; 101 | } 102 | } 103 | &__menu { 104 | align-items: center; 105 | justify-content: center; 106 | flex-direction: column; 107 | min-height: 100vh; 108 | background-color: $navbar-bg; 109 | padding: 2rem 0; // add some top / bottom padding in case there is more items that doesn't fit in the viewport 110 | } 111 | .menu-item { 112 | &:not(:last-child) { 113 | margin-bottom: 1rem; 114 | } 115 | } 116 | body.navbar--opened & { 117 | &__collapse { 118 | visibility: visible; 119 | opacity: 1; 120 | } 121 | &__toggler-line { 122 | &:nth-child(1) { 123 | top: 15px; 124 | transform: rotate(45deg); 125 | } 126 | &:nth-child(3) { 127 | top: 15px; 128 | transform: rotate(-45deg); 129 | } 130 | &:nth-child(2) { 131 | opacity: 0; 132 | } 133 | } 134 | } 135 | } 136 | 137 | @include media-breakpoint-up(md) { 138 | &__wrapper { 139 | height: $navbar-height-desktop; 140 | } 141 | &__brand { 142 | margin-right: auto; 143 | } 144 | &__menu { 145 | flex-direction: row; 146 | } 147 | .menu-item { 148 | &:not(:last-child) { 149 | margin-right: 2rem; 150 | } 151 | } 152 | } 153 | } 154 | 155 | // Prevent vertical scrollbar when navbar is opened on smaller devices 156 | 157 | body.navbar--opened { 158 | overflow: hidden; 159 | } 160 | 161 | /** 162 | * Navbar Fixed 163 | */ 164 | 165 | .navbar.navbar--fixed { 166 | position: fixed; 167 | top: 0; 168 | left: 0; 169 | width: 100%; 170 | } 171 | 172 | // Make navbar transparent when scrolling more than 100px down 173 | 174 | .navbar.navbar--scrolled { 175 | transition: $transition-base; 176 | opacity: .25; 177 | &:hover { 178 | opacity: 1; 179 | } 180 | } 181 | 182 | // When the navbar is fixed you should also add some padding to body tag as well - most likely that should be height of the navbar 183 | 184 | body { 185 | @include media-breakpoint-down(sm) { 186 | padding-top: $navbar-height-mobile; 187 | } 188 | @include media-breakpoint-up(md) { 189 | padding-top: $navbar-height-desktop; 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # There is more up to date boilerplate based on Gulp 4 and Webpack. Please consider using this one instead https://github.com/tomaszbujnowicz/frontie-webpack 2 | 3 | # Frontie - Front-end Boilerplate 4 | 5 | **Frontie is a front-end boilerplate using Gulp for task automation.** 6 | 7 | Based on normalize.css, Bootstrap 4 Grid & Responsive breakpoints and enhanced with Twig.js, Sass, Autoprefixer plus Browsersync. 8 | These tools make it a solid front-end boilerplate to get a new project off the ground. 9 | 10 | ## Features 11 | 12 | * [Gulp](http://gulpjs.com/) for task automation 13 | 14 | * [Bootstrap 4 Grid System](https://getbootstrap.com/docs/4.1/layout/grid/) as a powerful mobile-first flexbox grid to build layouts of all shapes and sizes 15 | 16 | * [Bootstrap 4 Responsive Breakpoints](https://getbootstrap.com/docs/4.1/layout/overview/#responsive-breakpoints) as a media queries to create sensible breakpoints 17 | 18 | * [Twig.js](https://github.com/twigjs/twig.js) as a templating engine 19 | 20 | * [Sass](http://sass-lang.com/) as a CSS preprocessor 21 | 22 | * [Autoprefixer](https://www.npmjs.org/package/gulp-autoprefixer) for parsing CSS and add vendor prefixes to rules by Can I Use 23 | 24 | * [Browsersync](https://www.browsersync.io/) for time-saving synchronised browser testing 25 | 26 | * [Github pages](https://www.npmjs.com/package/gulp-gh-pages) for publishing contents to Github pages 27 | 28 | * [Source Maps](https://www.npmjs.com/package/gulp-sourcemaps) 29 | 30 | ## Usage 31 | 32 | ### Requirements 33 | Make sure all dependencies have been installed before moving on: 34 | 35 | * [npm](https://www.npmjs.com/get-npm) or [yarn](https://yarnpkg.com/lang/en/) 36 | * [Node.js](https://nodejs.org/en/download/) 37 | * [Gulp](http://gulpjs.com/) 38 | 39 | ### Quick start: Installation 40 | Clone this repository and run 41 | - `npm install` or `yarn` to install dependencies 42 | 43 | This will take some time and will install all packages necessary to run Frontie and its tasks. 44 | 45 | ### Development 46 | - `gulp` to start the server (Browsersync session) and watch for changes 47 | 48 | Then visit http://localhost:3000/ *- or a new browser windows popped-up already -* to preview your new website. BrowserSync will automatically reload the CSS or refresh the whole page, when stylesheets, assets or content changes. 49 | 50 | **There are other tasks available including:** 51 | 52 | - `gulp watch` to watch without building /dist (production files) from scratch 53 | - `gulp build` to build a static version of the website inside the /dist folder 54 | - `gulp deploy` to publish contents from /dist folder to Github pages 55 | 56 | ## Structure 57 | 58 | ``` 59 | |--dist # → Static version of the website ready to upload (never edit) 60 | | 61 | |--node_modules # → Node.js packages (never edit) 62 | |--gulpfile.js # → Gulpfile tasks 63 | |--package.json # → Node.js dependencies and scripts 64 | |--package-lock.json # → Node.js lock file (never edit) 65 | |--yarn.lock # → Yarn lock file (never edit) 66 | | 67 | |--src # → Site source files 68 | | |--img # → Site images 69 | | |--css # → Site stylesheets 70 | | |--js # → Site JS 71 | | | |--components # → Components JS (e.g. navbar) 72 | | | |--vendor # → Vendor JS - 3rd party libraries 73 | | | |--main.js # → Main (custom scripts) JS 74 | | |--templates # → Site templates 75 | | | |--components # → Components templates (e.g. navbar) 76 | | | |--layouts # → Base templates 77 | | | |--partials # → Partial templates 78 | | | |--components.twig # → The components page for demo purpose 79 | | | |--index.twig # → The index page 80 | ``` 81 | 82 | ## Components 83 | 84 | There are also some default Frontie components ( with basic styling and functionality) included in the package. 85 | You can easily remove / comment them out in case you don't need them. 86 | 87 | * Navbar 88 | * Button 89 | 90 | ## Notes 91 | 92 | ### Why don't you include everything from Bootstrap 4? 93 | 94 | It's a really great front-end framework for many projects but in some cases it might be just too large and complex. 95 | I only took what I needed from it which is a grid system and responsive breakpoints. 96 | If you need more stuff then you can easily import required components or use a dedicated version [Frontie Bootstrap 4](https://github.com/tomaszbujnowicz/frontie-bootstrap4) 97 | 98 | ## Next Step? 99 | 100 | * Upgrade to use Gulp 4, Webpack and Babel or @std/esm 101 | 102 | ## Copyright and license 103 | 104 | Copyright 2018 Tomasz Bujnowicz under the [MIT license](http://opensource.org/licenses/MIT). 105 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Variables 3 | */ 4 | var gulp = require('gulp'), 5 | autoprefixer = require('gulp-autoprefixer'), 6 | browserSync = require('browser-sync'), 7 | changed = require('gulp-changed'), 8 | concat = require('gulp-concat'), 9 | del = require('del'), 10 | foreach = require('gulp-foreach'), 11 | ghPages = require('gulp-gh-pages'), 12 | notify = require('gulp-notify'), 13 | plumber = require('gulp-plumber'), 14 | reload = browserSync.reload, 15 | runSequence = require('run-sequence'), 16 | sass = require('gulp-sass'), 17 | sassGlob = require('gulp-sass-glob'), 18 | sassLint = require('gulp-sass-lint'), 19 | sourcemaps = require('gulp-sourcemaps'), 20 | twig = require('gulp-twig'), 21 | uglify = require('gulp-uglify'), 22 | watch = require('gulp-watch'); 23 | 24 | /** 25 | * Paths 26 | */ 27 | var paths = { 28 | dist: 'dist/', 29 | src: 'src/', 30 | deploy: 'dist/**/*', 31 | html: 'dist/*.html', 32 | browserSync: './dist', 33 | sass: { 34 | inputAll: 'src/sass/**/*.scss', 35 | input: 'src/sass/main.scss', 36 | output: 'dist/css', 37 | lint: 'src/sass/**/*.s+(a|c)ss' 38 | }, 39 | jsVendor: { 40 | input: 'src/js/vendor/**/*.js', 41 | output: 'dist/js' 42 | }, 43 | jsComponents: { 44 | input: 'src/js/components/**/*.js', 45 | }, 46 | js: { 47 | input: 'src/js/main.js', 48 | output: 'dist/js' 49 | }, 50 | img: { 51 | input: 'src/img/**/*', 52 | output: 'dist/img' 53 | }, 54 | twig: { 55 | src: 'src/templates/*.{twig,html}', 56 | watch: 'src/templates/**/*.{twig,html}' 57 | }, 58 | misc: { 59 | xml: 'src/*.xml', 60 | txt: 'src/*.txt' 61 | } 62 | }; 63 | 64 | /** 65 | * Catch stream errors 66 | */ 67 | var onError = function (err) { 68 | notify.onError({ 69 | title: "Gulp error in " + err.plugin, 70 | message: err.toString() 71 | })(err); 72 | }; 73 | 74 | /** 75 | * Browser Sync 76 | */ 77 | gulp.task('browser-sync', function() { 78 | browserSync.init(null, { 79 | files: [paths.html], 80 | server: { 81 | baseDir: paths.browserSync 82 | }, 83 | notify: false 84 | }); 85 | }); 86 | 87 | /** 88 | * Clean dist 89 | */ 90 | gulp.task('clean:dist', function() { 91 | return del.sync(paths.dist); 92 | }) 93 | 94 | /** 95 | * CSS 96 | */ 97 | gulp.task('css', function (done) { 98 | return gulp.src(paths.sass.input) 99 | .pipe(plumber({ errorHandler: onError })) 100 | .pipe(sourcemaps.init()) 101 | .pipe(sassGlob()) 102 | .pipe(sass({ outputStyle: 'compressed' })) 103 | .pipe(autoprefixer('last 2 versions')) 104 | .pipe(sourcemaps.write('./', {addComment: false})) 105 | .pipe(gulp.dest(paths.sass.output)) 106 | .pipe(browserSync.reload({stream:true})) 107 | done(); 108 | }); 109 | 110 | /** 111 | * Sass Lint 112 | */ 113 | gulp.task('sass-lint', function () { 114 | return gulp.src(paths.sass.lint) 115 | .pipe(sassLint()) 116 | .pipe(sassLint.format()) 117 | .pipe(sassLint.failOnError()) 118 | }); 119 | 120 | /** 121 | * JS Vendor 122 | */ 123 | gulp.task('js:vendor', function (done) { 124 | return gulp.src(paths.jsVendor.input) 125 | .pipe(plumber({ errorHandler: onError })) 126 | .pipe(sourcemaps.init()) 127 | .pipe(concat('vendor.js')) 128 | .pipe(uglify()) 129 | .pipe(sourcemaps.write('./', {addComment: false})) 130 | .pipe(gulp.dest(paths.jsVendor.output)) 131 | .pipe(browserSync.reload({stream:true})) 132 | done(); 133 | }); 134 | 135 | /** 136 | * JS Main 137 | */ 138 | gulp.task('js:main', function (done) { 139 | return gulp.src([ 140 | paths.js.input, 141 | paths.jsComponents.input 142 | ]) 143 | .pipe(plumber({ errorHandler: onError })) 144 | .pipe(sourcemaps.init()) 145 | .pipe(concat('main.min.js')) 146 | .pipe(uglify()) 147 | .pipe(sourcemaps.write('./', {addComment: false})) 148 | .pipe(gulp.dest(paths.js.output)) 149 | .pipe(browserSync.reload({stream:true})) 150 | done(); 151 | }); 152 | 153 | /** 154 | * Images 155 | */ 156 | gulp.task('images', function (done) { 157 | return gulp.src([ 158 | paths.img.input 159 | ], { 160 | 'dot': true // include hidden files 161 | }) 162 | .pipe(changed(paths.img.output)) 163 | .pipe(gulp.dest(paths.img.output)) 164 | .pipe(browserSync.reload({stream:true})) 165 | done(); 166 | }); 167 | 168 | /** 169 | * Twig 170 | */ 171 | gulp.task('twig', function (done) { 172 | return gulp.src(paths.twig.src) 173 | .pipe(plumber({ 174 | errorHandler: function (error) { 175 | console.log(error.message); 176 | this.emit('end'); 177 | }})) 178 | .pipe(foreach(function(stream,file){ 179 | return stream 180 | .pipe(twig()) 181 | })) 182 | .pipe(gulp.dest(paths.dist)) 183 | done(); 184 | }); 185 | 186 | /** 187 | * Copy miscellaneous files 188 | */ 189 | gulp.task('copy:misc', function (done) { 190 | return gulp.src([ 191 | paths.misc.xml, 192 | paths.misc.txt 193 | ]) 194 | .pipe(changed(paths.dist)) 195 | .pipe(gulp.dest(paths.dist)) 196 | .pipe(browserSync.reload({stream:true})) 197 | done(); 198 | }); 199 | 200 | /** 201 | * Task: Gulp Watch Sequence 202 | */ 203 | gulp.task('watch-files', function () { 204 | watch(paths.img.input, function () { 205 | gulp.start('images'); 206 | }); 207 | watch(paths.sass.inputAll, function () { 208 | gulp.start('css'); 209 | }); 210 | watch(paths.js.input, function () { 211 | gulp.start('js:main'); 212 | }); 213 | watch(paths.jsComponents.input, function () { 214 | gulp.start('js:main'); 215 | }); 216 | watch(paths.jsVendor.input, function () { 217 | gulp.start('js:vendor'); 218 | }); 219 | watch(paths.twig.watch, function () { 220 | gulp.start('twig'); 221 | }); 222 | watch([paths.misc.xml, paths.misc.txt], function () { 223 | gulp.start('copy:misc'); 224 | }); 225 | }); 226 | 227 | /** 228 | * Task: Gulp Default 229 | */ 230 | gulp.task('default', function(done) { 231 | runSequence('build', [ 232 | 'watch-files', 233 | 'browser-sync' 234 | ], done ) 235 | }); 236 | 237 | /** 238 | * Task: Gulp Build 239 | */ 240 | gulp.task('build', function (done) { 241 | runSequence('clean:dist', [ 242 | 'css', 243 | 'js:vendor', 244 | 'js:main', 245 | 'images', 246 | 'twig', 247 | 'copy:misc' 248 | ], done ) 249 | }) 250 | 251 | /** 252 | * Task: Gulp Watch 253 | */ 254 | gulp.task('watch', function(done) { 255 | runSequence('watch-files', [ 256 | 'browser-sync' 257 | ], done ) 258 | }); 259 | 260 | /** 261 | * Task: Gulp Deploy 262 | */ 263 | gulp.task('deploy', function() { 264 | return gulp.src(paths.deploy) 265 | .pipe(ghPages()); 266 | }); 267 | -------------------------------------------------------------------------------- /src/sass/vendor/_normalize.scss: -------------------------------------------------------------------------------- 1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /* Document 4 | ========================================================================== */ 5 | 6 | /** 7 | * 1. Correct the line height in all browsers. 8 | * 2. Prevent adjustments of font size after orientation changes in iOS. 9 | */ 10 | 11 | html { 12 | line-height: 1.15; /* 1 */ 13 | -webkit-text-size-adjust: 100%; /* 2 */ 14 | } 15 | 16 | /* Sections 17 | ========================================================================== */ 18 | 19 | /** 20 | * Remove the margin in all browsers. 21 | */ 22 | 23 | body { 24 | margin: 0; 25 | } 26 | 27 | /** 28 | * Render the `main` element consistently in IE. 29 | */ 30 | 31 | main { 32 | display: block; 33 | } 34 | 35 | /** 36 | * Correct the font size and margin on `h1` elements within `section` and 37 | * `article` contexts in Chrome, Firefox, and Safari. 38 | */ 39 | 40 | h1 { 41 | font-size: 2em; 42 | margin: 0.67em 0; 43 | } 44 | 45 | /* Grouping content 46 | ========================================================================== */ 47 | 48 | /** 49 | * 1. Add the correct box sizing in Firefox. 50 | * 2. Show the overflow in Edge and IE. 51 | */ 52 | 53 | hr { 54 | box-sizing: content-box; /* 1 */ 55 | height: 0; /* 1 */ 56 | overflow: visible; /* 2 */ 57 | } 58 | 59 | /** 60 | * 1. Correct the inheritance and scaling of font size in all browsers. 61 | * 2. Correct the odd `em` font sizing in all browsers. 62 | */ 63 | 64 | pre { 65 | font-family: monospace, monospace; /* 1 */ 66 | font-size: 1em; /* 2 */ 67 | } 68 | 69 | /* Text-level semantics 70 | ========================================================================== */ 71 | 72 | /** 73 | * Remove the gray background on active links in IE 10. 74 | */ 75 | 76 | a { 77 | background-color: transparent; 78 | } 79 | 80 | /** 81 | * 1. Remove the bottom border in Chrome 57- 82 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 83 | */ 84 | 85 | abbr[title] { 86 | border-bottom: none; /* 1 */ 87 | text-decoration: underline; /* 2 */ 88 | text-decoration: underline dotted; /* 2 */ 89 | } 90 | 91 | /** 92 | * Add the correct font weight in Chrome, Edge, and Safari. 93 | */ 94 | 95 | b, 96 | strong { 97 | font-weight: bolder; 98 | } 99 | 100 | /** 101 | * 1. Correct the inheritance and scaling of font size in all browsers. 102 | * 2. Correct the odd `em` font sizing in all browsers. 103 | */ 104 | 105 | code, 106 | kbd, 107 | samp { 108 | font-family: monospace, monospace; /* 1 */ 109 | font-size: 1em; /* 2 */ 110 | } 111 | 112 | /** 113 | * Add the correct font size in all browsers. 114 | */ 115 | 116 | small { 117 | font-size: 80%; 118 | } 119 | 120 | /** 121 | * Prevent `sub` and `sup` elements from affecting the line height in 122 | * all browsers. 123 | */ 124 | 125 | sub, 126 | sup { 127 | font-size: 75%; 128 | line-height: 0; 129 | position: relative; 130 | vertical-align: baseline; 131 | } 132 | 133 | sub { 134 | bottom: -0.25em; 135 | } 136 | 137 | sup { 138 | top: -0.5em; 139 | } 140 | 141 | /* Embedded content 142 | ========================================================================== */ 143 | 144 | /** 145 | * Remove the border on images inside links in IE 10. 146 | */ 147 | 148 | img { 149 | border-style: none; 150 | } 151 | 152 | /* Forms 153 | ========================================================================== */ 154 | 155 | /** 156 | * 1. Change the font styles in all browsers. 157 | * 2. Remove the margin in Firefox and Safari. 158 | */ 159 | 160 | button, 161 | input, 162 | optgroup, 163 | select, 164 | textarea { 165 | font-family: inherit; /* 1 */ 166 | font-size: 100%; /* 1 */ 167 | line-height: 1.15; /* 1 */ 168 | margin: 0; /* 2 */ 169 | } 170 | 171 | /** 172 | * Show the overflow in IE. 173 | * 1. Show the overflow in Edge. 174 | */ 175 | 176 | button, 177 | input { /* 1 */ 178 | overflow: visible; 179 | } 180 | 181 | /** 182 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 183 | * 1. Remove the inheritance of text transform in Firefox. 184 | */ 185 | 186 | button, 187 | select { /* 1 */ 188 | text-transform: none; 189 | } 190 | 191 | /** 192 | * Correct the inability to style clickable types in iOS and Safari. 193 | */ 194 | 195 | button, 196 | [type="button"], 197 | [type="reset"], 198 | [type="submit"] { 199 | -webkit-appearance: button; 200 | } 201 | 202 | /** 203 | * Remove the inner border and padding in Firefox. 204 | */ 205 | 206 | button::-moz-focus-inner, 207 | [type="button"]::-moz-focus-inner, 208 | [type="reset"]::-moz-focus-inner, 209 | [type="submit"]::-moz-focus-inner { 210 | border-style: none; 211 | padding: 0; 212 | } 213 | 214 | /** 215 | * Restore the focus styles unset by the previous rule. 216 | */ 217 | 218 | button:-moz-focusring, 219 | [type="button"]:-moz-focusring, 220 | [type="reset"]:-moz-focusring, 221 | [type="submit"]:-moz-focusring { 222 | outline: 1px dotted ButtonText; 223 | } 224 | 225 | /** 226 | * Correct the padding in Firefox. 227 | */ 228 | 229 | fieldset { 230 | padding: 0.35em 0.75em 0.625em; 231 | } 232 | 233 | /** 234 | * 1. Correct the text wrapping in Edge and IE. 235 | * 2. Correct the color inheritance from `fieldset` elements in IE. 236 | * 3. Remove the padding so developers are not caught out when they zero out 237 | * `fieldset` elements in all browsers. 238 | */ 239 | 240 | legend { 241 | box-sizing: border-box; /* 1 */ 242 | color: inherit; /* 2 */ 243 | display: table; /* 1 */ 244 | max-width: 100%; /* 1 */ 245 | padding: 0; /* 3 */ 246 | white-space: normal; /* 1 */ 247 | } 248 | 249 | /** 250 | * Add the correct vertical alignment in Chrome, Firefox, and Opera. 251 | */ 252 | 253 | progress { 254 | vertical-align: baseline; 255 | } 256 | 257 | /** 258 | * Remove the default vertical scrollbar in IE 10+. 259 | */ 260 | 261 | textarea { 262 | overflow: auto; 263 | } 264 | 265 | /** 266 | * 1. Add the correct box sizing in IE 10. 267 | * 2. Remove the padding in IE 10. 268 | */ 269 | 270 | [type="checkbox"], 271 | [type="radio"] { 272 | box-sizing: border-box; /* 1 */ 273 | padding: 0; /* 2 */ 274 | } 275 | 276 | /** 277 | * Correct the cursor style of increment and decrement buttons in Chrome. 278 | */ 279 | 280 | [type="number"]::-webkit-inner-spin-button, 281 | [type="number"]::-webkit-outer-spin-button { 282 | height: auto; 283 | } 284 | 285 | /** 286 | * 1. Correct the odd appearance in Chrome and Safari. 287 | * 2. Correct the outline style in Safari. 288 | */ 289 | 290 | [type="search"] { 291 | -webkit-appearance: textfield; /* 1 */ 292 | outline-offset: -2px; /* 2 */ 293 | } 294 | 295 | /** 296 | * Remove the inner padding in Chrome and Safari on macOS. 297 | */ 298 | 299 | [type="search"]::-webkit-search-decoration { 300 | -webkit-appearance: none; 301 | } 302 | 303 | /** 304 | * 1. Correct the inability to style clickable types in iOS and Safari. 305 | * 2. Change font properties to `inherit` in Safari. 306 | */ 307 | 308 | ::-webkit-file-upload-button { 309 | -webkit-appearance: button; /* 1 */ 310 | font: inherit; /* 2 */ 311 | } 312 | 313 | /* Interactive 314 | ========================================================================== */ 315 | 316 | /* 317 | * Add the correct display in Edge, IE 10+, and Firefox. 318 | */ 319 | 320 | details { 321 | display: block; 322 | } 323 | 324 | /* 325 | * Add the correct display in all browsers. 326 | */ 327 | 328 | summary { 329 | display: list-item; 330 | } 331 | 332 | /* Misc 333 | ========================================================================== */ 334 | 335 | /** 336 | * Add the correct display in IE 10+. 337 | */ 338 | 339 | template { 340 | display: none; 341 | } 342 | 343 | /** 344 | * Add the correct display in IE 10. 345 | */ 346 | 347 | [hidden] { 348 | display: none; 349 | } 350 | -------------------------------------------------------------------------------- /src/sass/base/_mixins.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Mixins 3 | */ 4 | 5 | /** 6 | * Clearfix 7 | * Usage: 8 | @include clearfix; 9 | */ 10 | @mixin clearfix() { 11 | &::after { 12 | display: block; 13 | clear: both; 14 | content: ""; 15 | } 16 | } 17 | 18 | /** 19 | * Unstyled keeps list items block level, just removes default browser padding and list-style. 20 | * Usage: 21 | @include list-none; 22 | */ 23 | @mixin list-none { 24 | list-style: none; 25 | padding-left: 0; 26 | } 27 | 28 | /** 29 | * Overlay 30 | * Usage 31 | @include overlay(); 32 | */ 33 | @mixin overlay() { 34 | position: absolute; 35 | top: 0; 36 | right: 0; 37 | bottom: 0; 38 | left: 0; 39 | } 40 | 41 | /** 42 | * Pseudo elements after / before 43 | * Usage 44 | @include pseudo; 45 | */ 46 | @mixin pseudo($display: block, $position: absolute, $content: ''){ 47 | content: $content; 48 | display: $display; 49 | position: $position; 50 | } 51 | 52 | /** 53 | * Set max width for an element and make it centered 54 | * Usage 55 | @include max-width(600px); 56 | */ 57 | @mixin max-width($max-width) { 58 | max-width: $max-width; 59 | margin-right: auto; 60 | margin-left: auto; 61 | } 62 | 63 | /** 64 | * https://github.com/nicholasruggeri/px-to-rem-sass-mixin 65 | * Usage 66 | font-size: rem(20) 67 | margin: rem(40) rem(40); 68 | */ 69 | @function strip-units($value) { 70 | @return ($value / ($value * 0 + 1)); 71 | } 72 | @function rem($pxval) { 73 | @if not unitless($pxval) { 74 | $pxval: strip-units($pxval); 75 | } 76 | $base: 16px; 77 | @if not unitless($base) { 78 | $base: strip-units($base); 79 | } 80 | @return ($pxval / $base) * 1rem; 81 | } 82 | 83 | /** 84 | * Responsive font size for different media query breakpoints 85 | * Usage 86 | @include responsive-font-size(12px, 14px, 16px, 18px, 20px); 87 | @include responsive-font-size(xs, sm, md, lg, xl); 88 | 89 | * In case you want to omit the media query breakpoint please use '' 90 | e.g. @include responsive-font-size(1rem, '', '', 1.5rem, '', 2.5rem); 91 | */ 92 | @mixin responsive-font-size($font-size-xs: null, $font-size-sm: null, $font-size-md: null, $font-size-lg: null, $font-size-xl: null) { 93 | @if ($font-size-xs != '') { 94 | font-size: $font-size-xs; 95 | } 96 | @if ($font-size-sm != '') { 97 | @include media-breakpoint-up(sm) { 98 | font-size: $font-size-sm; 99 | } 100 | } 101 | @if ($font-size-md != '') { 102 | @include media-breakpoint-up(md) { 103 | font-size: $font-size-md; 104 | } 105 | } 106 | @if ($font-size-lg != '') { 107 | @include media-breakpoint-up(lg) { 108 | font-size: $font-size-lg; 109 | } 110 | } 111 | @if ($font-size-xl != '') { 112 | @include media-breakpoint-up(xl) { 113 | font-size: $font-size-xl; 114 | } 115 | } 116 | } 117 | 118 | /** 119 | * Responsive spacing for different media query breakpoints 120 | * Usage 121 | @include responsive-space('mb', 10px, 20px, 30px, 40px, 50px); 122 | @include responsive-space('type, xs, sm, md, lg, xl); 123 | 124 | * In case you want to omit the media query breakpoint please use '' 125 | e.g. @include responsive-space('mb', 10px, '', '', 40px, 50px); 126 | 127 | Type: 128 | 129 | m : margin 130 | mt : margin-top 131 | mr : margin-right 132 | mb : margin-bottom 133 | ml : margin-left 134 | mx : (horizontal) margin-left and margin-right 135 | my : (vertical) margin-top and margin bottom 136 | 137 | p : padding 138 | pt : padding-top 139 | pr : padding-right 140 | pb : padding-bottom 141 | pl : padding-left 142 | px : (horizontal) padding-left and padding-right 143 | py : (vertical) padding-top and padding bottom 144 | */ 145 | @mixin responsive-space($type: null, $space-xs: null, $space-sm: null, $space-md: null, $space-lg: null, $space-xl: null, $type_1: null, $type_2: null) { 146 | @if ($type == 'm') { 147 | $type: 'margin'; 148 | } 149 | @if ($type == 'mt') { 150 | $type: 'margin-top'; 151 | } 152 | @if ($type == 'mr') { 153 | $type: 'margin-right'; 154 | } 155 | @if ($type == 'mb') { 156 | $type: 'margin-bottom'; 157 | } 158 | @if ($type == 'ml') { 159 | $type: 'margin-left'; 160 | } 161 | @if ($type == 'mx') { 162 | $type_1: 'margin-left'; 163 | $type_2: 'margin-right'; 164 | } 165 | @if ($type == 'my') { 166 | $type_1: 'margin-top'; 167 | $type_2: 'margin-bottom'; 168 | } 169 | 170 | @if ($type == 'p') { 171 | $type: 'padding'; 172 | } 173 | @if ($type == 'pt') { 174 | $type: 'padding-top'; 175 | } 176 | @if ($type == 'pr') { 177 | $type: 'padding-right'; 178 | } 179 | @if ($type == 'pb') { 180 | $type: 'padding-bottom'; 181 | } 182 | @if ($type == 'pl') { 183 | $type: 'padding-left'; 184 | } 185 | @if ($type == 'px') { 186 | $type_1: 'padding-left'; 187 | $type_2: 'padding-right'; 188 | } 189 | @if ($type == 'py') { 190 | $type_1: 'padding-top'; 191 | $type_2: 'padding-bottom'; 192 | } 193 | 194 | @if ( ($type == 'mx') or ($type == 'my') or ($type == 'py') or ($type == 'px') ) { 195 | @if ($space-xs != '') { 196 | #{$type_1}: $space-xs; 197 | #{$type_2}: $space-xs; 198 | } 199 | @if ($space-sm != '') { 200 | @include media-breakpoint-up(sm) { 201 | #{$type_1}: $space-sm; 202 | #{$type_2}: $space-sm; 203 | } 204 | } 205 | @if ($space-md != '') { 206 | @include media-breakpoint-up(md) { 207 | #{$type_1}: $space-md; 208 | #{$type_2}: $space-md; 209 | } 210 | } 211 | @if ($space-lg != '') { 212 | @include media-breakpoint-up(lg) { 213 | #{$type_1}: $space-lg; 214 | #{$type_2}: $space-lg; 215 | } 216 | } 217 | @if ($space-xl != '') { 218 | @include media-breakpoint-up(xl) { 219 | #{$type_1}: $space-xl; 220 | #{$type_2}: $space-xl; 221 | } 222 | } 223 | } @else { 224 | @if ($space-xs != '') { 225 | #{$type}: $space-xs; 226 | } 227 | @if ($space-sm != '') { 228 | @include media-breakpoint-up(sm) { 229 | #{$type}: $space-sm; 230 | } 231 | } 232 | @if ($space-md != '') { 233 | @include media-breakpoint-up(md) { 234 | #{$type}: $space-md; 235 | } 236 | } 237 | @if ($space-lg != '') { 238 | @include media-breakpoint-up(lg) { 239 | #{$type}: $space-lg; 240 | } 241 | } 242 | @if ($space-xl != '') { 243 | @include media-breakpoint-up(xl) { 244 | #{$type}: $space-xl; 245 | } 246 | } 247 | } 248 | } 249 | 250 | /** 251 | * Responsive size for different media query breakpoints 252 | * Usage 253 | @include responsive-size('h', 10px, 20px, 30px, 40px, 50px); 254 | @include responsive-size('type, xs, sm, md, lg, xl); 255 | 256 | * In case you want to omit the media query breakpoint please use '' 257 | e.g. @include responsive-size('h', 10px, '', '', 40px, 50px); 258 | 259 | Type: 260 | 261 | h : height, 262 | minh : min-height, 263 | maxh : max-height, 264 | w : width, 265 | minw : min-width, 266 | maxw : max-width 267 | */ 268 | @mixin responsive-size($type: null, $size-xs: null, $size-sm: null, $size-md: null, $size-lg: null, $size-xl: null) { 269 | @if ($type == 'h') { 270 | $type: 'height'; 271 | } 272 | @if ($type == 'w') { 273 | $type: 'width'; 274 | } 275 | @if ($type == 'minh') { 276 | $type: 'min-height'; 277 | } 278 | @if ($type == 'minw') { 279 | $type: 'min-width'; 280 | } 281 | @if ($type == 'maxh') { 282 | $type: 'max-height'; 283 | } 284 | @if ($type == 'maxw') { 285 | $type: 'max-width'; 286 | } 287 | @if ($size-xs != '') { 288 | #{$type}: $size-xs; 289 | } 290 | @if ($size-sm != '') { 291 | @include media-breakpoint-up(sm) { 292 | #{$type}: $size-sm; 293 | } 294 | } 295 | @if ($size-md != '') { 296 | @include media-breakpoint-up(md) { 297 | #{$type}: $size-md; 298 | } 299 | } 300 | @if ($size-lg != '') { 301 | @include media-breakpoint-up(lg) { 302 | #{$type}: $size-lg; 303 | } 304 | } 305 | @if ($size-xl != '') { 306 | @include media-breakpoint-up(xl) { 307 | #{$type}: $size-xl; 308 | } 309 | } 310 | } 311 | --------------------------------------------------------------------------------