├── CONTRIBUTING.md ├── .gitignore ├── package.json ├── Gruntfile.js ├── LICENSE ├── example ├── css │ └── style.css └── index.html ├── README.md └── src └── sticky.js /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | 1. Fork it! 4 | 2. Create your feature branch: `git checkout -b my-new-feature` 5 | 3. Commit your changes: `git commit -m 'Add some feature'` 6 | 4. Push to the branch: `git push origin my-new-feature` 7 | 5. Submit a pull request :D 8 | 9 | English is the universal language nowadays, so please don't create or comment on issues using another language. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Deployed apps should consider commenting this line out: 24 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 25 | node_modules 26 | 27 | # OSX 28 | .DS_Store 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sticky", 3 | "description": "VanillaJS + CSS3 Sticky Header", 4 | "version": "2.0.0", 5 | "private": true, 6 | "author": "Pedro Rogério", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "devDependencies": { 11 | "grunt": "~0.4.5", 12 | "grunt-contrib-watch": "~0.6.1", 13 | "grunt-contrib-uglify": "~0.9.2" 14 | }, 15 | "repository": "https://github.com/pinceladasdaweb/sticky", 16 | "bugs": { 17 | "url": "https://github.com/pinceladasdaweb/sticky/issues" 18 | }, 19 | "licenses": [{ 20 | "type": "MIT", 21 | "url": "http://opensource.org/licenses/MIT" 22 | }] 23 | } -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | "use strict"; 3 | 4 | var pkg = grunt.file.readJSON("package.json"), 5 | date = new Date(); 6 | 7 | grunt.initConfig({ 8 | meta: { 9 | banner: '/*! ' + pkg.name + ' ' + pkg.version + ' | (c) ' + date.getFullYear() + ' ' + pkg.author + ' | ' + pkg.licenses[0].type + ' License */' 10 | }, 11 | uglify: { 12 | options: { 13 | banner: '<%= meta.banner %>\n' 14 | }, 15 | target: { 16 | files: { 17 | 'build/sticky.min.js': ['src/sticky.js'] 18 | } 19 | } 20 | }, 21 | watch: { 22 | js: { 23 | files: ['src/sticky.js'], 24 | tasks: ['uglify'] 25 | } 26 | } 27 | }); 28 | 29 | grunt.loadNpmTasks('grunt-contrib-watch'); 30 | grunt.loadNpmTasks('grunt-contrib-uglify'); 31 | 32 | grunt.registerTask('default', [ 'uglify', ]); 33 | }; 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Pedro Rogério 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /example/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font: 62.5% 'Raleway', sans-serif; 3 | margin: 0 4 | } 5 | 6 | main, header, nav { 7 | display: block; 8 | } 9 | 10 | h1 { 11 | font-size: 7em; 12 | margin: 0 13 | } 14 | 15 | h2 { 16 | font-size: 3em; 17 | } 18 | 19 | p { 20 | font-size: 1.4em; 21 | line-height: 18px 22 | } 23 | 24 | img { 25 | display: block; 26 | max-width: 100% 27 | } 28 | 29 | a { 30 | color: #fff 31 | } 32 | 33 | .container { 34 | margin: auto; 35 | max-width: 800px; 36 | padding: 0 15px 37 | } 38 | 39 | .banner { 40 | background-color: #64C6AF; 41 | color: #fff; 42 | padding: 60px; 43 | text-align: center 44 | } 45 | 46 | .banner p { 47 | font-size: 3em; 48 | line-height: 26px; 49 | margin: 20px 0 40px; 50 | } 51 | 52 | .button { 53 | background: #F77156; 54 | cursor: pointer; 55 | display: block; 56 | font-size: 1.6em; 57 | margin: 0 auto; 58 | padding: 13px; 59 | text-decoration: none; 60 | text-transform: uppercase; 61 | width: 200px; 62 | } 63 | 64 | nav { 65 | background-color: #64C6AF; 66 | height: 70px; 67 | left: 0; 68 | position: fixed; 69 | top: 0; 70 | width: 100%; 71 | 72 | /* Translate -100% to move off screen */ 73 | -webkit-transform: translateY(-100%); 74 | -moz-transform: translateY(-100%); 75 | -ms-transform: translateY(-100%); 76 | transform: translateY(-100%); 77 | 78 | /* Animations */ 79 | -webkit-transition: all 300ms ease-in-out; 80 | -moz-transition: all 300ms ease-in-out; 81 | transition: all 300ms ease-in-out; 82 | } 83 | 84 | nav p { 85 | color: #fff; 86 | font-size: 3em; 87 | line-height: 70px; 88 | margin: 0; 89 | text-align: center; 90 | } 91 | 92 | .sticky { 93 | -webkit-transform: translateY(0%); 94 | -moz-transform: translateY(0%); 95 | -ms-transform: translateY(0%); 96 | transform: translateY(0%); 97 | } 98 | 99 | /* For Old IEs */ 100 | .no-transitions nav { 101 | top: -70px; 102 | } 103 | 104 | .no-transitions .sticky { 105 | top: 0; 106 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sticky 2 | > Vanilla JS + CSS3 Sticky Header. 3 | 4 | ## What is it? 5 | Sticky creates an on-demand sticky header. Specify when you want your header to become fixed and the rest is magic. [Demo](http://www.pinceladasdaweb.com.br/blog/uploads/sticky/). 6 | 7 | ## Getting Started 8 | 9 | ```bash 10 | # Get the latest snapshot 11 | $ git clone git@github.com:pinceladasdaweb/sticky.git 12 | ``` 13 | 14 | ## How to use? 15 | Sticky is a [Vanilla JS](http://vanilla-js.com/) plugin with no dependancies. Include the [`sticky.min.js`](build/sticky.min.js) before your `````` tag and initialise it: 16 | 17 | ```html 18 | 19 | 25 | ``` 26 | 27 | Loading Sticky via AMD (require.js): 28 | 29 | ```html 30 | 38 | ``` 39 | 40 | ## Options 41 | The script expect the following values: 42 | 43 | | Value | Description | 44 | | ---------------------------------- |:-----------------------------------------------------------:| 45 | | **target** | Element tagname, element class or element id | 46 | | **offset** | Scroll offset | 47 | 48 | ##Browser Support 49 | 50 | ![IE](https://cloud.githubusercontent.com/assets/398893/3528325/20373e76-078e-11e4-8e3a-1cb86cf506f0.png) | ![Chrome](https://cloud.githubusercontent.com/assets/398893/3528328/23bc7bc4-078e-11e4-8752-ba2809bf5cce.png) | ![Firefox](https://cloud.githubusercontent.com/assets/398893/3528329/26283ab0-078e-11e4-84d4-db2cf1009953.png) | ![Opera](https://cloud.githubusercontent.com/assets/398893/3528330/27ec9fa8-078e-11e4-95cb-709fd11dac16.png) | ![Safari](https://cloud.githubusercontent.com/assets/398893/3528331/29df8618-078e-11e4-8e3e-ed8ac738693f.png) 51 | --- | --- | --- | --- | --- | 52 | IE 9+ ✔ | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | 53 | 54 | ## Contributing 55 | 56 | Check [CONTRIBUTING.md](CONTRIBUTING.md) for more information. 57 | 58 | ## History 59 | 60 | Check [Releases](https://github.com/pinceladasdaweb/sticky/releases) for detailed changelog. 61 | 62 | ## License 63 | [MIT](LICENSE) -------------------------------------------------------------------------------- /src/sticky.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true, debug: true*/ 2 | /*global define, module, exports*/ 3 | (function (root, factory) { 4 | "use strict"; 5 | if (typeof define === 'function' && define.amd) { 6 | define([], factory); 7 | } else if (typeof exports === 'object') { 8 | module.exports = factory(); 9 | } else { 10 | root.Sticky = factory(); 11 | } 12 | }(this, function () { 13 | "use strict"; 14 | var Sticky = function (options) { 15 | if (!this || !(this instanceof Sticky)) { 16 | return new Sticky(options); 17 | } 18 | 19 | if (!options) { 20 | options = {}; 21 | } 22 | 23 | this.target = options.target; 24 | this.offset = options.offset; 25 | 26 | this.ready(); 27 | }; 28 | 29 | Sticky.prototype = { 30 | hasClass: function (el, name) { 31 | return new RegExp('(\\s|^)' + name + '(\\s|$)').test(el.className); 32 | }, 33 | addClass: function (el, name) { 34 | if (!this.hasClass(el, name)) { 35 | el.className += (el.className ? ' ' : '') + name; 36 | } 37 | }, 38 | removeClass: function (el, name) { 39 | if (this.hasClass(el, name)) { 40 | el.className = el.className.replace(new RegExp('(\\s|^)' + name + '(\\s|$)'), ' ').replace(/^\s+|\s+$/g, ''); 41 | } 42 | }, 43 | supportTrans: function () { 44 | var s = document.body.style, 45 | supports = 'transition' in s || 'WebkitTransition' in s || 'MozTransition' in s || 'msTransition' in s || 'OTransition' in s; 46 | 47 | return supports; 48 | }, 49 | scrollPos: function () { 50 | if (window.pageYOffset !== undefined) { 51 | return pageYOffset; 52 | } else { 53 | var root = document.documentElement, 54 | body = document.body, 55 | scrollY; 56 | 57 | scrollY = root.scrollTop || body.scrollTop || 0; 58 | return scrollY; 59 | } 60 | }, 61 | trigger: function (eventName) { 62 | var event = document.createEvent('HTMLEvents'); 63 | event.initEvent(eventName, true, false); 64 | 65 | window.dispatchEvent(event); 66 | }, 67 | handler: function () { 68 | this.trigger('scroll'); 69 | }, 70 | attach: function (el) { 71 | if (this.scrollPos() > this.offset) { 72 | this.addClass(el, 'sticky'); 73 | } else { 74 | this.removeClass(el, 'sticky'); 75 | } 76 | }, 77 | ready: function () { 78 | var root = document.documentElement, 79 | el = document.querySelector(this.target), 80 | events = ['DOMContentLoaded', 'load', 'resize'], 81 | i, 82 | len; 83 | 84 | if (!this.supportTrans()) { 85 | this.addClass(root, 'no-transitions'); 86 | } 87 | 88 | window.addEventListener('scroll', function () { 89 | this.attach(el); 90 | }.bind(this), false); 91 | 92 | for (i = 0, len = events.length; i < len; i += 1) { 93 | window.addEventListener(events[i], this.handler(), false); 94 | } 95 | } 96 | }; 97 | 98 | return Sticky; 99 | })); -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sticky - Vanilla JS + CSS3 Sticky Header 5 | 6 | 7 | 17 | 18 | 19 | 20 | 21 | 22 | 27 | 28 | 35 | 36 |
37 |
38 |

Scroll to see it in action

39 | 40 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus neque nibh, dignissim pulvinar ligula non, sagittis lobortis lectus. Ut a nibh enim. Sed venenatis dignissim enim et laoreet. Aliquam a hendrerit dui, eget viverra magna. Pellentesque eu eros porttitor metus tempor sagittis. Morbi eget leo eros. Sed rhoncus sagittis neque, vitae lobortis dolor cursus a. Mauris non porta ipsum. Curabitur id enim cursus tortor luctus hendrerit eu et augue. Pellentesque eu nisl ante.

41 | 42 |

Praesent in dui feugiat, pulvinar justo vitae, ultrices libero. Donec bibendum magna sed porta tempor. Ut adipiscing lacus eu nibh blandit, sed pharetra nibh tristique. Ut vitae tortor pharetra, rhoncus arcu quis, vulputate neque. Phasellus eu leo vitae ligula molestie vulputate quis a turpis. Aenean ut risus in orci vulputate feugiat. Mauris porta, velit eu viverra viverra, augue justo vehicula justo, vel consectetur sapien lacus lacinia augue. Morbi tincidunt tellus at dolor sollicitudin posuere. Suspendisse consequat pretium quam, at mollis neque tempus at. Phasellus at urna vestibulum, imperdiet turpis quis, sagittis risus.

43 | 44 |

Vivamus quis consectetur velit, sed pellentesque magna. Ut laoreet risus eu risus porttitor sagittis. Vestibulum sed libero a dui rhoncus bibendum. Ut mattis lectus eget tincidunt iaculis. Phasellus vitae sem tempor, rutrum felis ut, hendrerit lacus. Nulla eleifend vestibulum ipsum, ac elementum enim iaculis nec. Vestibulum dictum quam nec euismod lobortis. Nullam et arcu eu risus hendrerit volutpat quis at metus. Curabitur at mauris sed magna rutrum gravida quis nec leo. Aenean fermentum fermentum sem, et scelerisque quam pharetra eget. In molestie iaculis erat, ac adipiscing leo vehicula non. Duis dignissim lectus purus, at elementum massa aliquam vel.

45 | 46 | Visit placehold.it 47 | 48 |

Donec quis libero vulputate, pellentesque odio in, aliquam purus. Donec luctus nisi sit amet convallis dictum. Nunc tristique mollis odio. Ut sodales condimentum suscipit. Duis tincidunt molestie molestie. Cras dignissim vestibulum neque, vel euismod orci cursus nec. Aliquam at sem sem. Fusce fringilla ipsum eget diam malesuada consequat.

49 | 50 |

Mauris et vehicula dui, ut gravida massa. Nam vulputate massa nec vestibulum fringilla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed porttitor sed est sit amet dapibus. Mauris fermentum felis sem, feugiat vulputate elit varius at. Mauris congue felis eget ultricies congue. Aliquam sed libero quis neque tincidunt pretium quis ut dui. Aliquam malesuada fringilla nisi, et porta enim aliquam eu. Etiam vehicula metus lorem, ut eleifend dolor venenatis a.

51 | 52 |

Praesent sem nibh, vestibulum nec turpis vitae, accumsan dapibus lorem. Aliquam malesuada leo quis nunc pretium, eu congue ante mattis. Pellentesque et viverra nisi. Cras porta lacus luctus lectus pharetra suscipit. Etiam pulvinar ipsum vel ipsum porttitor, non imperdiet magna blandit. Suspendisse potenti. Aliquam erat volutpat. Sed sit amet consectetur libero. Nullam a odio quis quam tristique suscipit.

53 | 54 | Visit placehold.it 55 | 56 |

Proin eget sapien ullamcorper, laoreet nunc vel, egestas eros. Aenean ut convallis turpis. Proin purus turpis, aliquet eu aliquet at, facilisis eu turpis. Cras pulvinar sem libero, a tempus dui laoreet vitae. Donec a rutrum orci. Aliquam dictum ac dui et ultrices. Proin sit amet pulvinar nulla. Nunc eros turpis, pulvinar id dui id, tincidunt tincidunt metus. Donec ullamcorper nisi non faucibus elementum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.

57 | 58 |

Suspendisse diam ante, ultricies nec placerat at, eleifend vitae odio. Donec eget consectetur turpis, at bibendum quam. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Morbi ac gravida lorem. Ut scelerisque urna felis, vel accumsan justo congue non. Integer dictum erat vel nibh tempor, nec lacinia est pellentesque. Sed rhoncus ac nulla eget tristique. Praesent aliquet risus eget purus dapibus dignissim. Integer convallis justo tellus, in congue eros dignissim et. Sed in nisi condimentum dui sodales pellentesque non sit amet neque. Cras ipsum purus, interdum quis nisl et, egestas bibendum magna. Nulla bibendum elementum magna ac imperdiet.

59 |
60 |
61 | 62 | 63 | 69 | 70 | --------------------------------------------------------------------------------