From: Antonio Ospite Date: Thu, 29 Jun 2017 14:28:50 +0000 (+0200) Subject: Initial import X-Git-Url: https://git.ao2.it/experiments/scss-responsive-toggle-menu.git/commitdiff_plain/49a35944e1e79a1ccad4b0837a2ad1f5416a2801?ds=inline Initial import --- 49a35944e1e79a1ccad4b0837a2ad1f5416a2801 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..32bf1bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.sass-cache/ +css/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0bd2c7a --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +SCSS_SOURCE_DIR := scss +SCSS_SOURCES := $(wildcard $(SCSS_SOURCE_DIR)/[^_]*.scss) + +CSS_DEST_DIR := css +CSS_COMPILED := $(SCSS_SOURCES:$(SCSS_SOURCE_DIR)/%.scss=%.css) + +SCSS_OUTPUT_TYPE := expanded + +SCSS_BIN := sassc +SCSS_FLAGS := -t $(SCSS_OUTPUT_TYPE) + +update: $(CSS_COMPILED) + +clean: + rm -rf $(CSS_DEST_DIR) .sass-cache + +%.css: $(SCSS_SOURCE_DIR)/%.scss + @[ -d $(CSS_DEST_DIR) ] || mkdir -p $(CSS_DEST_DIR) + $(SCSS_BIN) $(SCSS_FLAGS) $< $(CSS_DEST_DIR)/$@ diff --git a/README b/README new file mode 100644 index 0000000..4150448 --- /dev/null +++ b/README @@ -0,0 +1,40 @@ +An SCSS mixin for pure CSS responsive toggle menus without hacks. + +The selectors name follows the BEM scheme, the file structure follows SMACSS. + +Inspired by: + - http://bradfrost.com/blog/web/responsive-nav-patterns/ + - http://www.creativebloq.com/css3/build-smart-mobile-navigation-without-hacks-6122800 + - https://gist.github.com/joesnellpdx/4151902 + - https://codepen.io/joesnellpdx/pen/ktGdx + + +Dependencies: + - sassc or ruby-sass + + +Demo: + 1. Install 'sassc', on Debian systems: + $ sudo apt-get install sassc + 2. Download this code. + 3. Run 'make' to build the final css style. + 4. Load the page: + $ xdg-open index.html + + +How it works +============ + +In HTML, linking to an element using its fragment id allows to pass some state +info to the page via the URL and then capture it in the CSS :target selector. + +Moreover HTML specifies the behavior of scrolling when navigating to +a fragment id, in particular the specification says: "if the destination is +not being rendered the User Agent must do nothing", see also +https://www.w3.org/TR/html5/single-page.html#scroll-to-fragid + +So, according to the specification linking to an hidden element using its +fragment id does not cause any scrolling. + +This behavior is to use a simple link as a mechanism to set the states of the +menu (show, hide) and style them in CSS. diff --git a/index.html b/index.html new file mode 100644 index 0000000..d098b89 --- /dev/null +++ b/index.html @@ -0,0 +1,67 @@ + + + + + + + Toggle Navigation: No JS + + + + + + + + + + + +

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ + + +

Another Menu

+ + + +

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ + + diff --git a/scss/_modules.scss b/scss/_modules.scss new file mode 100644 index 0000000..db3ba12 --- /dev/null +++ b/scss/_modules.scss @@ -0,0 +1,2 @@ +@import "modules/_toggle-menu"; +@import "modules/_font-icons"; diff --git a/scss/modules/_font-icons.scss b/scss/modules/_font-icons.scss new file mode 100644 index 0000000..c6cf78a --- /dev/null +++ b/scss/modules/_font-icons.scss @@ -0,0 +1,11 @@ +// Inspired by http://jaydenseric.com/blog/fun-with-sass-and-font-icons +// To be more portable a well defined font-family should be used for icons. + +@function icon($icon) { + $icons: ( + cross: "\2715", + hamburger: "\2630", + ); + + @return map-get($icons, $icon); +} diff --git a/scss/modules/_toggle-menu.scss b/scss/modules/_toggle-menu.scss new file mode 100644 index 0000000..1cb6f4d --- /dev/null +++ b/scss/modules/_toggle-menu.scss @@ -0,0 +1,174 @@ +// toggle-menu - An SCSS mixin for pure CSS responsive toggle menus +// +// Copyright (C) 2017 Antonio Ospite +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +@mixin _toggle-menu-common($show-menu-id) { + + /* common fallback style for when :target is not supported */ + .toggle-menu { + .toggle-menu__target { + display: none; + } + + .toggle-menu__button--show { + display: none; + } + + .toggle-menu__button--hide { + display: none; + } + + .toggle-menu__list .toggle-menu__item { + height: auto; + } + } + + /* common mobile-first style for when :taget is supported */ + body:not(:target) .toggle-menu { + .toggle-menu__list .toggle-menu__item { + overflow: hidden; + height: 0; + } + + .toggle-menu__button--show { + display: block; + } + + .toggle-menu__button--hide { + display: none; + } + } + + @media screen and (min-width: 48.25em) { + body:not(:target) .toggle-menu { + .toggle-menu__list .toggle-menu__item { + display: inline-block; + overflow: inherit; + } + } + } +} + +@mixin _toggle-menu-theme { + + .toggle-menu { + + a { + color: white; + text-decoration: none; + } + + .toggle-menu__button { + cursor: pointer; + line-height: 2em; + padding: .5em; + font-weight: bold; + + &:after { + content: icon(hamburger); + font-size: 2em; + float: right; + } + } + + .toggle-menu__button--show { + background-color: red; + } + + .toggle-menu__button--hide { + background-color: darkred; + &:after { + content: icon(cross); + } + } + + .toggle-menu__list { + background-color: orange; + list-style-type: none; + margin-top: 0; + padding: 0; + } + + .toggle-menu__list .toggle-menu__item { + a { + color: black; + padding: .5em 1em; + display: block; + + } + :hover { + background-color: yellow; + } + } + } +} + + +$imported-once: false !default; +@mixin toggle-menu-common($show-menu-id) { + $imported-once: $imported-once !global; + @if ($imported-once == false) { + $imported-once: true !global; + @include _toggle-menu-common($show-menu-id); + @include _toggle-menu-theme; + } +} + +@mixin toggle-menu($show-menu-id) { + + @include toggle-menu-common($show-menu-id); + + /* mobile-first style for ##{$show-menu-id} when :target is supported */ + body:not(:target) .toggle-menu { + ##{$show-menu-id}:target { + ~ .toggle-menu__list .toggle-menu__item { + height: auto; + -moz-transition: height .25s, line-height .25s; + -ms-transition: height .25s, line-height .25s; + -o-transition: height .25s, line-height .25s; + -webkit-transition: height .25s, line-height .25s; + transition: height .25s, line-height .25s; + } + + ~ .toggle-menu__button--show { + display: none; + } + + ~ .toggle-menu__button--hide { + display: block; + } + } + } + + /* big screen style for ##{$show-menu-id} when :target is supported */ + @media screen and (min-width: 48.25em) { + body:not(:target) .toggle-menu { + ##{$show-menu-id}, ##{$show-menu-id}:target { + ~ .toggle-menu__list .toggle-menu__item { + height: auto; + } + + ~ .toggle-menu__button--show { + display: none; + } + + ~ .toggle-menu__button--hide { + display: none; + } + } + } + } +} diff --git a/scss/style.scss b/scss/style.scss new file mode 100644 index 0000000..4994fb6 --- /dev/null +++ b/scss/style.scss @@ -0,0 +1,6 @@ +@charset 'utf-8'; + +@import "_modules"; + +@include toggle-menu("show-nav-menu"); +@include toggle-menu("show-nav-menu-2");