From 899f947b7930bd3e6e6c64142b055b77ebe89806 Mon Sep 17 00:00:00 2001 From: Thomas Higginbotham Date: Fri, 18 Mar 2016 13:46:24 -0400 Subject: [PATCH] Initial commit --- .gitignore | 5 + Gruntfile.js | 41 ++++ LICENSE.txt | 21 ++ README.md | 91 ++++++++ css/main.css | 480 ++++++++++++++++++++++++++++++++++++++ demo.html | 359 ++++++++++++++++++++++++++++ gulpfile.js | 37 +++ package.json | 28 +++ scss/main.scss | 8 + scss/modules/_config.scss | 5 + scss/modules/_grids.scss | 252 ++++++++++++++++++++ scss/vendor/_demo.scss | 242 +++++++++++++++++++ 12 files changed, 1569 insertions(+) create mode 100644 .gitignore create mode 100644 Gruntfile.js create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 css/main.css create mode 100644 demo.html create mode 100644 gulpfile.js create mode 100644 package.json create mode 100644 scss/main.scss create mode 100644 scss/modules/_config.scss create mode 100644 scss/modules/_grids.scss create mode 100644 scss/vendor/_demo.scss diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2c4a13e --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.DS_Store +.sass-cache +node_modules +css/maps +*.min.css diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..f64dc5d --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,41 @@ +module.exports = function(grunt) { + 'use strict'; + + // Configuration + grunt.initConfig({ + sass: { + dev: { + options: { + style: 'expanded' + }, + files: { + 'css/main.css': 'scss/main.scss' + } + }, + dist: { + options: { + style: 'compressed' + }, + files: { + 'css/main.min.css': 'scss/main.scss' + } + } + }, + watch: { + sass: { + files: ['scss/**/*.scss'], + tasks: ['sass:dev'], + options: { + spawn: false, + atBegin: true + } + } + } + }); + + // Tasks + grunt.loadNpmTasks('grunt-contrib-sass'); + grunt.loadNpmTasks('grunt-contrib-watch'); + + grunt.registerTask('default', ['sass:dist']); +}; diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..79e919e --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Thomas Higginbotham + +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: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..93e86da --- /dev/null +++ b/README.md @@ -0,0 +1,91 @@ +# Raven Framework + +Raven is a flexible, pluggable framework that is used to build everything from the most simplistic marketing websites to highly advanced web applications. At its core is a finely tuned grid system used for creating responsive layouts using Sass. It’s extensible architecture makes it easy to integrate with other systems, so you can add in whatever you need, whether it be a Grunt/Gulp build system, a unit testing environment, or an opinionated JavaScript framework. Here are some of the “add-ins” currently in development: + +* **Raven Dev Environment** – Work in real-time with Sass auto-compilation and LiveReload, then build optimized code for production environments. +* **Raven Pattern Library** – Add a style guide and auto-updated documentation to your project, based on the principles of atomic design. +* **Raven UI** – Take advantage of common interfaces like carousels, accordions, off-canvas menus, and more. +* **Raven Forms** – Improve your form layouts and styles. +* **Raven RequireJS** – Create AMD-compliant JavaScript modules and keep your code organized. +* **Raven Unit Tests** – Write unit tests with Karma and Jasmine. Then automate them with Grunt or Gulp using the PhantomJS headless browser. +* **Raven Code Collaboration** – Specify EditorConfig rules and common linting configurations for your team. +* **Raven High-DPI Sprites** – Use the Compass sprite map generator to create separate sprite maps for low- and high-DPI images. + +...and more to come. + +## Getting Started + +Use your preferred method to download the files. + +* Yeoman: `npm install -g generator-raven-framework` then `yo raven-framework` +* Bower: `bower install raven-framework` +* NPM: `npm i raven-framework` +* Git: `git clone https://github.com/thomashigginbotham/raven-framework.git` +* Download a ZIP file + +Regardless of how you get the files, you’ll see a **demo.html** file. Open it in your browser and your code editor for more details on using Raven. + +## Using the Grid system + +Creating grids should be easy. If you have to remember to add an `end` class to the last element in a row, or if you have to include additional `
` tags in order to apply a simple background color, then your grid system is not making things easy for you. Doing more with less code should be the mantra, and Raven delivers. + +### Rows and Columns + +Use the `row()` mixin when you need a row of columns. + +HTML +``` +
+ +
L. Frank Baum
+
J. K. Rowling
+
+``` + +SCSS +``` +.authors { + @include row(50% 25% 25%); +} +``` + +In the example above, we will have a row with three columns, each with the name of an author. The first column will fill half the page (50%). The two remaining columns will each take up a quarter of the page (25% each). + +Even more impressive, you can mix units! That’s, right — try out something like `@include row(200px 100% 200px)` to get that perfect layout. + +### Galleries + +The `gallery()` mixin is for creating multiple rows and columns where the columns are all the same width (think of a thumbnail image grid). + +HTML +``` + + + +``` + +SCSS +``` +ul { + @include gallery(2); +} +``` + +The above will create a 2-column grid of image thumbnails. If you continue to add thumbnails, they will automatically wrap to the next row, keeping the 2-column layout. + +For additional grid features, see the **demo.html** file and the Sass files. + +### Compiling Your Sass + +Raven uses Sass to provide a number of advantages — semantic HTML classes, no bloat from unused CSS, and of course, the variables, functions, and mixins. See the Sass website for instructions on installing Sass. + +For more advanced developers, take advantage of the minimal Gulp or Grunt config files to compile your Sass changes as you work. See the config files for details. + +### Copyright/License + +Raven Framework is freely available under the [MIT license](https://tldrlegal.com/license/mit-license). diff --git a/css/main.css b/css/main.css new file mode 100644 index 0000000..73327fe --- /dev/null +++ b/css/main.css @@ -0,0 +1,480 @@ +body { + tab-size: 4; + line-height: 1.6; + color: #111; + background-color: #fff; +} + +code { + background-color: #eee; +} + +pre { + padding: 1rem; + max-height: 400px; + font-size: .875em; + color: #eee; + background-color: #363669; +} +pre code { + display: block; + background-color: #363669; +} + +a { + color: #2c2c6f; +} + +h1, +h2, +h3, +h4, +h5, +h6, +p, +ul, +ol, +dl, +pre { + margin-top: 0; +} + +h1 { + font-size: 2.6rem; + line-height: 1.2; + color: #2c2c6f; +} + +h3 { + margin-bottom: 0; + font-size: 1em; +} + +section { + margin-bottom: 3rem; +} +section:last-child { + margin-bottom: 0; +} + +.page-wrapper { + margin: 0 auto; + padding: 2rem; + max-width: 1400px; +} +@media (min-width: 1100px) { + .page-wrapper { + box-sizing: border-box; + display: flex; + justify-content: space-between; + } + .page-wrapper > * { + box-sizing: border-box; + margin-right: 2rem; + } + .page-wrapper > *:last-child { + margin-right: 0; + } + .page-wrapper > :nth-child(1) { + flex-grow: 0; + flex-shrink: 0; + flex-basis: 15rem; + } + .page-wrapper > :nth-child(2) { + flex-grow: 1; + flex-shrink: 1; + flex-basis: calc(100% - 0rem - .1px); + } + .page-wrapper > :nth-child(2) { + order: 1; + margin-right: 2rem; + } + .page-wrapper > :nth-child(1) { + order: 2; + margin-right: 0; + } +} + +.page-nav { + margin-bottom: 2rem; + padding: 1rem; + background-color: #eee; +} +.page-nav h2 { + margin-bottom: 1rem; +} +.page-nav ul { + margin: 0; + padding: 0; + list-style: none; +} +.page-nav ul ul { + display: none; + margin-left: 1rem; +} +.page-nav a { + text-decoration: none; +} +.page-nav a:hover { + text-decoration: underline; +} +@media (min-width: 1100px) { + .page-nav { + margin-bottom: 0; + } + .page-nav .content-wrapper { + position: fixed; + } + .page-nav ul ul { + display: block; + } +} + +.page-footer { + padding: 2rem; + text-align: center; + color: #fff; + background-color: #2c2c6f; +} +.page-footer p { + margin: 0 auto; + max-width: 1400px; +} +.page-footer a { + text-decoration: underline; + color: #fff; +} + +.message-info { + margin-bottom: 2rem; + padding: 1rem; + border: 2px dashed #ccc; +} +.message-info:last-child { + margin-bottom: 0; +} +.message-info > :first-child { + margin-top: 0; +} +.message-info > :last-child { + margin-bottom: 0; +} + +.sample { + margin-bottom: 2rem; + padding: 1rem; + border: 1px solid #ccc; + text-align: center; + list-style: none; +} +.sample > * { + margin-bottom: 2rem; + padding: 2rem; + background: #ccc; +} +.sample > *:last-child { + margin-bottom: 0; +} +@media (min-width: 640px) { + .sample > * { + margin-bottom: 0; + } +} + +@media (min-width: 640px) { + .simple-percents { + box-sizing: border-box; + display: block; + } + .simple-percents > * { + box-sizing: border-box; + margin-right: 2rem; + } + .simple-percents > *:last-child { + margin-right: 0; + } + .simple-percents::before { + content: ''; + display: table; + line-height: 0; + clear: both; + } + .simple-percents::after { + content: ''; + display: table; + line-height: 0; + clear: both; + } + .simple-percents > * { + float: left; + } + .simple-percents > *:last-child { + float: right; + } + .simple-percents > *:first-child:last-child { + float: left; + } + .simple-percents > :nth-child(1) { + width: calc(25% - 1.5rem - .1px); + } + .simple-percents > :nth-child(2) { + width: calc(25% - 1.5rem - .1px); + } + .simple-percents > :nth-child(3) { + width: calc(50% - 1rem - .1px); + } + + .x-of-y { + box-sizing: border-box; + display: block; + } + .x-of-y > * { + box-sizing: border-box; + margin-right: 2rem; + } + .x-of-y > *:last-child { + margin-right: 0; + } + .x-of-y::before { + content: ''; + display: table; + line-height: 0; + clear: both; + } + .x-of-y::after { + content: ''; + display: table; + line-height: 0; + clear: both; + } + .x-of-y > * { + float: left; + } + .x-of-y > *:last-child { + float: right; + } + .x-of-y > *:first-child:last-child { + float: left; + } + .x-of-y > :nth-child(1) { + width: calc(16.66667% - 1.66667rem - .1px); + } + .x-of-y > :nth-child(2) { + width: calc(33.33333% - 1.33333rem - .1px); + } + .x-of-y > :nth-child(3) { + width: calc(50% - 1rem - .1px); + } + + .holy-grail { + box-sizing: border-box; + display: flex; + } + .holy-grail > * { + box-sizing: border-box; + margin-right: 2rem; + } + .holy-grail > *:last-child { + margin-right: 0; + } + .holy-grail > :nth-child(1) { + flex-grow: 0; + flex-shrink: 0; + flex-basis: 200px; + } + .holy-grail > :nth-child(2) { + flex-grow: 1; + flex-shrink: 1; + flex-basis: calc(100% - 0rem - .1px); + } + .holy-grail > :nth-child(3) { + flex-grow: 0; + flex-shrink: 0; + flex-basis: 200px; + } + + .sample-parent { + box-sizing: border-box; + display: block; + } + .sample-parent > * { + box-sizing: border-box; + margin-right: 2rem; + } + .sample-parent > *:last-child { + margin-right: 0; + } + .sample-parent::before { + content: ''; + display: table; + line-height: 0; + clear: both; + } + .sample-parent::after { + content: ''; + display: table; + line-height: 0; + clear: both; + } + .sample-parent > * { + float: left; + } + .sample-parent > *:last-child { + float: right; + } + .sample-parent > *:first-child:last-child { + float: left; + } + .sample-parent > :nth-child(1) { + width: calc(25% - 1.5rem - .1px); + } + .sample-parent > :nth-child(2) { + width: calc(75% - 0.5rem - .1px); + } + + .sample-nested { + box-sizing: border-box; + display: flex; + } + .sample-nested > * { + box-sizing: border-box; + margin-right: 2rem; + } + .sample-nested > *:last-child { + margin-right: 0; + } + .sample-nested > :nth-child(1) { + flex-grow: 0; + flex-shrink: 0; + flex-basis: 5em; + } + .sample-nested > :nth-child(2) { + flex-grow: 1; + flex-shrink: 1; + flex-basis: calc(100% - 0rem - .1px); + } + .sample-nested > * { + background-color: #eee; + } + + .simple-center { + box-sizing: border-box; + display: flex; + justify-content: center; + } + .simple-center > * { + box-sizing: border-box; + margin-right: 2rem; + } + .simple-center > *:last-child { + margin-right: 0; + } + .simple-center > :nth-child(1) { + flex-grow: 0; + flex-shrink: 0; + flex-basis: 15rem; + } + .simple-center > :nth-child(2) { + flex-grow: 0; + flex-shrink: 0; + flex-basis: 15rem; + } + + .simple-reorder { + box-sizing: border-box; + display: flex; + justify-content: space-between; + } + .simple-reorder > * { + box-sizing: border-box; + margin-right: 2rem; + } + .simple-reorder > *:last-child { + margin-right: 0; + } + .simple-reorder > :nth-child(1) { + flex-grow: 1; + flex-shrink: 1; + flex-basis: calc(33.33333% - 1.33333rem - .1px); + } + .simple-reorder > :nth-child(2) { + flex-grow: 1; + flex-shrink: 1; + flex-basis: calc(33.33333% - 1.33333rem - .1px); + } + .simple-reorder > :nth-child(3) { + flex-grow: 1; + flex-shrink: 1; + flex-basis: calc(33.33333% - 1.33333rem - .1px); + } + .simple-reorder > :nth-child(3) { + order: 1; + margin-right: 2rem; + } + .simple-reorder > :nth-child(1) { + order: 2; + margin-right: 2rem; + } + .simple-reorder > :nth-child(2) { + order: 3; + margin-right: 0; + } + + .list-gallery { + box-sizing: border-box; + list-style: none; + display: block; + } + .list-gallery > *:nth-child(1n) { + margin-bottom: 2rem; + } + .list-gallery > *:nth-last-child(-n + 3) { + margin-bottom: 0; + } + .list-gallery::before { + content: ''; + display: table; + line-height: 0; + clear: both; + } + .list-gallery::after { + content: ''; + display: table; + line-height: 0; + clear: both; + } + .list-gallery > * { + box-sizing: border-box; + width: calc(33.33333% - 1.33333rem - .1px); + } + .list-gallery > *:nth-child(1n) { + clear: none; + float: left; + margin-right: 2rem; + } + .list-gallery > *:nth-child(3n-2) { + clear: both; + } + .list-gallery > *:nth-child(3n) { + float: right; + margin-right: 0; + } + + .list-equal-cols { + box-sizing: border-box; + list-style: none; + display: flex; + width: 100%; + } + .list-equal-cols > * { + margin-right: 2rem; + flex-basis: 100%; + } + .list-equal-cols > *:last-child { + margin-right: 0; + } +} + + + +/*# sourceMappingURL=maps/main.css.map */ diff --git a/demo.html b/demo.html new file mode 100644 index 0000000..f2a99e7 --- /dev/null +++ b/demo.html @@ -0,0 +1,359 @@ + + + + + Raven Framework Starter Page + + + + + +
+ + +
+

Raven Framework Starter Page

+ +
+

Introduction

+

This simple starter page provides some basic information and examples for working with Raven. When you’re ready to start building, just follow these quick steps:

+ +
    +
  1. Delete the file at scss/vendor/_demo.scss and the reference to it in scss/main.scss.
  2. +
  3. Remove the content of this HTML file or create a new one.
  4. +
  5. Write your HTML and Sass.
  6. +
+
+ +
+

About Raven

+

Still here? Let me tell you about some of the cool things Raven provides and how you can get the most out of it.

+

At its core, Raven is just a CSS grid system that uses Sass. If that’s all you need, no problem, we won’t be pushy. But just so you’re aware, Raven is an extensible framework with much more to offer.

+ +
    +
  • Raven Dev Environment* — Work in real-time with Sass auto-compilation and LiveReload. Then build optimized code for production environments.
  • +
  • Raven Pattern Library* — Add a style guide and auto-updated documentation to your project, based on the principles of atomic design.
  • +
  • Raven UI* — Take advantage of common interfaces such as carousels, accordions, off-canvas menus, and more.
  • +
  • Raven Forms* — Improve your form layouts and styles.
  • +
  • Raven RequireJS* — Create AMD-compliant JavaScript modules and keep your code organized.
  • +
  • Raven Unit Tests* — Write unit tests with Karma and Jasmine. Then automate them with Grunt or Gulp using the PhantomJS headless browser.
  • +
  • Raven Code Collab* — Specify EditorConfig rules and common linting configurations for your team.
  • +
  • Raven High-DPI Sprites* — Use the Compass sprite map generator to create separate sprite maps for low- and high-DPI images.
  • +
+ +

* These components are currently in development.

+
+ +
+

Configuration

+

Raven is very light-weight. Basically, you get this file, a few Sass files, and sample Grunt and Gulp configuration files. If you don’t use Grunt or Gulp, not to worry — you can delete those files and forget you ever saw them. All you need to know is how to work with Sass.

+ +
+

See the Build Systems section at the bottom of this page for more details about using Grunt and Gulp.

+
+ +

File Structure

+

The Sass file structure is as follows:

+ +
▾ scss
+  ▾ modules
+      _config.scss
+      _grids.scss
+  ▾ partials
+  ▾ vendor
+      _demo.scss
+    main.scss
+ +

The modules directory contains functions, mixins, and any file that doesn’t output any CSS. Style definitions for headers, footers, and other components should be placed in the partials directory. Finally, the vendor directory is for third-party style sheets.

+ +

The main.scss file should only contain imports to other Sass files. Remember to update it every time you want to include a new Sass file.

+ +

Settings

+

Raven currently provides only two settings: gutters and layout. Be assured, if there were more settings that we deemed useful, they’d be here. Some frameworks provide a ton of configuration options, but most of them just complicate things with no real benefit. Memorizing numerous options on the off-chance you need one doesn’t seem like a beneficial use of time.

+ +

To change Raven’s settings, open the scss/modules/_config.scss file and update the values. Change the space between columns by editing the gutters value, and change the layout method value to either float or flexbox. Flexbox is the preferred layout method, but if you need to support older browsers, you should leave it set to float.

+
+ +
+

Grid Layouts

+

The grid system allows you to specify your columns in an intuitive way. Simply pass the width of each column to the row() mixin. The row() mixin accepts three parameters: column-spans (a string of column widths), [column-gutter] (the space between columns), and [layout] (float or flexbox). Only column-spans is required. The gutters and layout method can be defined globally.

+ +

HTML

+
<div class="sample-row">
+	<div>25%</div>
+	<div>25%</div>
+	<div>50%</div>
+</div>
+ +

Sass

+
.sample-row {
+	@include row(25% 25% 50%);
+}
+ +

Result

+ +
+
25%
+
25%
+
50%
+
+ +

You can even mix units within a row. In the following example, the left and right columns will always by 200px wide, but the center column will stretch to the fill the remaining space.

+ +

HTML

+
<div class="sample-row">
+	<div>200px</div>
+	<div>100%</div>
+	<div>200px</div>
+</div>
+ +

Sass

+
.sample-row {
+	@include row(200px 100% 200px);
+}
+ +

Result

+ +
+
200px
+
100%
+
200px
+
+ +
+

Note: A Flexbox layout will be automatically triggered when using units other than percentages. Keep this in mind if you need to support older browsers.

+
+ +

If you prefer the more traditional grids (e.g., 2 out of 12 columns), you can use the following syntax.

+ +

HTML

+
<div class="sample-row">
+	<div>2 of 12</div>
+	<div>4 of 12</div>
+	<div>6 of 12</div>
+</div>
+ +

Sass

+
.sample-row {
+	@include row(200%/12 400%/12 600%/12);
+}
+		
+ +

Result

+ +
+
2 of 12
+
4 of 12
+
6 of 12
+
+
+ +
+

Nested Rows

+ +

Nesting rows is easy. Just use the same row() mixin on the child rows.

+ +

HTML

+
<div class="sample-parent">
+	<div>25%</div>
+
+	<div class="sample-nested">
+		<div>5em</div>
+		<div>100%</div>
+	</div>
+</div>
+ +

Sass

+
.sample-parent {
+	@include row(25% 75%);
+}
+
+.sample-nested {
+	@include row(5em 100%);
+}
+ +
+
25%
+ +
+
5em
+
100%
+
+
+
+ +
+

Centered Columns

+ +

Easily center columns using the native justify-content CSS property.

+ +

HTML

+
<div class="sample-row">
+	<div>15rem</div>
+	<div>15rem</div>
+</div>
+ +

Sass

+
.sample-row {
+	@include row(15rem 15rem);
+	justify-content: center;
+}
+ +

Result

+ +
+
15rem
+
15rem
+
+ +
+

Note: If you want to center columns with percentage width values, you will have to use Flexbox layout. This can be configured globally or by passing the $layout:flexbox argument to the row() mixin.

+
+
+ +
+

Column Reordering

+ +

The column-order() mixin can easily reorder columns for you — none of that push/pull columns nonsense that other frameworks use.

+ +

HTML

+
<div class="sample-row">
+	<div>First</div>
+	<div>Second</div>
+	<div>Third</div>
+</div>
+ +

Sass

+
.sample-row {
+	@include row(100%/3 100%/3 100%/3, $layout: flexbox);
+	@include column-order(3 1 2);
+}
+ +

Result

+ +
+
First
+
Second
+
Third
+
+ +
+

Note: The column-order() mixin makes use of Flexbox, so set it globally or pass it as an argument as in the example above.

+
+
+ + + +
+

Equal Columns

+ +

Sometimes it just isn’t possible to know how many columns will go in your row. For example, you may need to create a horizontal menu that will be managed by authors in a content management system. In these cases, the equal-columns() mixin is helpful.

+

The sample below can have any number of columns, and they will automatically adjust to fill the row.

+ +

HTML

+
<ul class="sample-row">
+	<li>1</li>
+	<li>2</li>
+	<li>3</li>
+	<li>4</li>
+</ul>
+ +

Sass

+
.sample-row {
+	@include equal-columns($layout: flexbox);
+}
+ +

Result

+ +
    +
  • 1
  • +
  • 2
  • +
  • 3
  • +
  • 4
  • +
+ +
+

We use display: table when Flexbox is not specified. If you decide not to use the Flexbox layout, be aware that you may need to tweak some margins and spacing around the container element.

+
+
+ +
+

Build Systems

+

If you are familiar with Grunt or Gulp, you will notice that Raven comes with config files for both. Follow these steps:

+ +
    +
  1. Delete the config file you don’t need (either Gruntfile.js or gulpfile.js).
  2. +
  3. Open package.json and remove the dependencies you won’t be using. For example, if you will be using Gulp, you may remove all of the Grunt dependencies.
  4. +
  5. Run npm install from the root directory of this project.
  6. +
+ +

Grunt

+

Use grunt watch to automatically compile your Sass into CSS as you make changes. Run grunt by itself to generate optimized CSS.

+ +

Gulp

+

Use gulp watch to automatically compile your Sass into CSS as you make changes. Run gulp by itself to generate optimized CSS.

+ +
+

If you’re looking for a more robust development environment, consider using Raven Dev Environment.

+
+
+
+
+ + + + diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..621d70f --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,37 @@ +'use strict'; + +var gulp = require('gulp'); +var sass = require('gulp-ruby-sass'); +var sourcemaps = require('gulp-sourcemaps'); +var rename = require('gulp-rename'); + +gulp.task('sass:dev', function() { + return sass('./scss/**/*.scss', {style: 'expanded', sourcemap: true}) + .on('error', sass.logError) + .pipe(sourcemaps.write('maps', { + includeContent: false, + sourceRoot: '/scss' + })) + .pipe(gulp.dest('css')); +}); + +gulp.task('sass:dist', function() { + return sass('scss/**/*.scss', {style: 'compressed', sourcemap: true}) + .on('error', sass.logError) + .pipe(rename({ + suffix: '.min' + })) + .pipe(sourcemaps.write('maps', { + includeContent: false, + sourceRoot: '/scss' + })) + .pipe(gulp.dest('css')); +}); + +gulp.task('default', ['sass:dist']); + +gulp.task('watch', ['sass:dev', 'sass:watch']); + +gulp.task('sass:watch', function() { + gulp.watch('./scss/**/*.scss', ['sass:dev']); +}); diff --git a/package.json b/package.json new file mode 100644 index 0000000..7904a1f --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "name": "raven-framework", + "version": "0.0.1", + "description": "A flexible, pluggable framework with a responsive grid system.", + "author": "Thomas Higginbotham", + "main": "scss/modules/_grids.scss", + "repository": { + "type": "git", + "url": "https://github.com/thomashigginbotham/raven-framework.git" + }, + "keywords": [ + "sass", + "responsive", + "grid", + "layout", + "flexbox" + ], + "license": "MIT", + "devDependencies": { + "grunt": "^0.4.5", + "grunt-contrib-sass": "^1.0.0", + "grunt-contrib-watch": "^0.6.1", + "gulp": "^3.9.1", + "gulp-rename": "^1.2.2", + "gulp-ruby-sass": "^2.0.6", + "gulp-sourcemaps": "^1.6.0" + } +} diff --git a/scss/main.scss b/scss/main.scss new file mode 100644 index 0000000..e7e7f80 --- /dev/null +++ b/scss/main.scss @@ -0,0 +1,8 @@ +// Raven configuration +@import 'modules/config'; + +// Grid functions and mixins +@import 'modules/grids'; + +// Demo CSS (remove) +@import 'vendor/demo'; diff --git a/scss/modules/_config.scss b/scss/modules/_config.scss new file mode 100644 index 0000000..12545ba --- /dev/null +++ b/scss/modules/_config.scss @@ -0,0 +1,5 @@ +// Global configuration +$raven: ( + gutters: 2rem, + layout: float +); diff --git a/scss/modules/_grids.scss b/scss/modules/_grids.scss new file mode 100644 index 0000000..4240639 --- /dev/null +++ b/scss/modules/_grids.scss @@ -0,0 +1,252 @@ +// Returns a value for the width property of a column. +// +// $column-width - The width of the column. +// $column-count - The total number of columns in the row. +// $column-gutter - The space between columns. +// $layout - Use "float" or "flexbox" for layout. +@function get-column-width($column-width, $column-count, $column-gutter: map-get($raven, gutters), $layout: map-get($raven, layout)) { + @if unit($column-width) == '%' { + // Percentage width column + @if $column-gutter > 0 { + @return calc(#{$column-width} - #{$column-gutter * (1 - $column-width / 100%)} - .1px); + } @else { + @return $column-width; + } + } @elseif $layout == flexbox { + // Fixed-width column with Flexbox + @return $column-width; + } @else { + // Cannot use floats with non-percentage width values + @return auto; + } +} + +// Provides syntactic sugar for getting the global gutter setting. +@function get-gutter() { + @return map-get($raven, gutters); +} + +// Returns true if the provided list has only percentage values. +// +// $list - The list of values to check. +@function has-only-percents($list) { + @each $item in $list { + @if unit($item) != '%' { + @return false; + } + } + + @return true; +} + +// Clears floats by adding ::before and/or ::after pseudo-selectors +// +// $before - Clear floats before the current element. +// $after - Clear floats after the current element. +// +// Compatible with Chrome, Firefox, Safari, IE 9+ +@mixin clear-floats($before: true, $after: true) { + @if $before { + &::before { + content: ''; + display: table; + line-height: 0; + clear: both; + } + } + + @if $after { + &::after { + content: ''; + display: table; + line-height: 0; + clear: both; + } + } +} + +// Creates a row of columns with the specified widths. +// +// $column-spans - A list of column widths (e.g., 25% 65% 20rem). +// $column-gutter - The space between columns. +// $layout - Use "float" or "flexbox" for layout. Only percentage values +// can be used for float layouts. +// +// Compatibility unknown. +@mixin row($column-spans, $column-gutter: map-get($raven, gutters), $layout: map-get($raven, layout)) { + // Force flexbox layout if column-spans are not given in percentages + @if not(has-only-percents($column-spans)) { + $layout: flexbox; + } + + box-sizing: border-box; + + > * { + box-sizing: border-box; + margin-right: $column-gutter; + + &:last-child { + margin-right: 0; + } + } + + @if $layout == flexbox { + display: flex; + } @else { + @include clear-floats; + display: block; + + > * { + float: left; + + &:last-child { + float: right; + } + + &:first-child:last-child { + float: left; + } + } + } + + @for $i from 1 through length($column-spans) { + > :nth-child(#{$i}) { + @if $layout == flexbox { + @if (unit(nth($column-spans, $i)) == '%') { + flex-grow: 1; + flex-shrink: 1; + } @else { + flex-grow: 0; + flex-shrink: 0; + } + + flex-basis: get-column-width(nth($column-spans, $i), length($column-spans), $column-gutter, $layout); + } @else { + width: get-column-width(nth($column-spans, $i), length($column-spans), $column-gutter, $layout); + } + } + } +} + +// Reorders the display of columns within a row (flexbox only). +// +// $order - A list of child orders (e.g., 2 3 1). +// $column-gutter - The space between columns. +// +// Compatibility unknown. +@mixin column-order($order, $column-gutter: map-get($raven, gutters)) { + justify-content: space-between; + + @for $i from 1 through length($order) { + > :nth-child(#{nth($order, $i)}) { + order: $i; + + @if $i < length($order) { + margin-right: $column-gutter; + } @else { + margin-right: 0; + } + } + } +} + +// Displays immediate child elements in rows and columns. +// +// $column-count - The number of columns in the gallery. +// $column-gutter - The space between columns. +// $layout - Use "float" or "flexbox". +// +// Compatibility unknown. +@mixin gallery($column-count, $column-gutter: map-get($raven, gutters), $layout: map-get($raven, layout)) { + $first-column-cell: #{$column-count}n-#{$column-count - 1}; + $last-column-cell: #{$column-count}n; + $last-row: unquote('-n + #{$column-count}'); + + box-sizing: border-box; + list-style: none; + + > * { + // Each cell should have bottom margin... + &:nth-child(1n) { + margin-bottom: $column-gutter; + } + + // ...except for cells in the last row. + &:nth-last-child(#{$last-row}) { + margin-bottom: 0; + } + } + + @if $layout == flexbox { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + align-items: flex-start; + + > * { + box-sizing: border-box; + flex: 0 0 get-column-width(1 / $column-count * 100%, $column-count, $column-gutter, $layout); + + } + } @else { + @include clear-floats; + display: block; + + > * { + box-sizing: border-box; + width: get-column-width(1 / $column-count * 100%, $column-count, $column-gutter, $layout); + + &:nth-child(1n) { + clear: none; + float: left; + margin-right: $column-gutter; + } + + // First cell of each row should clear the cells above it + &:nth-child(#{$first-column-cell}) { + clear: both; + } + + // Last cell in each row should float right + &:nth-child(#{$last-column-cell}) { + float: right; + margin-right: 0; + } + } + } +} + +// Displays all child elements in a single row with equal width. +// +// $column-gutter - The space between columns. +// +// Compatibility unknown. +@mixin equal-columns($column-gutter: map-get($raven, gutters), $layout: map-get($raven, layout)) { + box-sizing: border-box; + list-style: none; + + @if $layout == flexbox { + display: flex; + width: 100%; + + > * { + margin-right: $column-gutter; + flex-basis: 100%; + + &:last-child { + margin-right: 0; + } + } + } @else { + display: table; + table-layout: fixed; + border-spacing: $column-gutter 0; + margin-left: -$column-gutter; + width: calc(100% + #{2 * $column-gutter}); + + > * { + display: table-cell; + width: 2%; + } + } +} diff --git a/scss/vendor/_demo.scss b/scss/vendor/_demo.scss new file mode 100644 index 0000000..bc8a29b --- /dev/null +++ b/scss/vendor/_demo.scss @@ -0,0 +1,242 @@ +// Vars +$color_primary: #2c2c6f; +$color-primary-desaturated: #363669; +$color-grey-light: #eee; +$color-grey: #ccc; +$color-text: #111; +$color-bg: #fff; + +$canvas-small: 640px; +$canvas-medium: 1024px; +$canvas-large: 1100px; +$canvas-limit: 1400px; + +// Resets +body { + tab-size: 4; + line-height: 1.6; + color: $color-text; + background-color: $color-bg; +} + +code { + background-color: $color-grey-light; +} + +pre { + padding: 1rem; + max-height: 400px; + font-size: .875em; + color: $color-grey-light; + background-color: $color-primary-desaturated; + + code { + display: block; + background-color: $color-primary-desaturated; + } +} + +a { + color: $color-primary; +} + +h1, +h2, +h3, +h4, +h5, +h6, +p, +ul, +ol, +dl, +pre { + margin-top: 0; +} + +h1 { + font-size: 2.6rem; + line-height: 1.2; + color: $color-primary; +} + +h3 { + margin-bottom: 0; + font-size: 1em; +} + +section { + margin-bottom: get-gutter() * 1.5; + + &:last-child { + margin-bottom: 0; + } +} + +// Layout +.page-wrapper { + margin: 0 auto; + padding: get-gutter(); + max-width: $canvas-limit; + + @media (min-width: $canvas-large) { + @include row(15rem 100%, $layout: flexbox); + @include column-order(2 1); + } +} + +// Menu +.page-nav { + margin-bottom: get-gutter(); + padding: 1rem; + background-color: $color-grey-light; + + h2 { + margin-bottom: 1rem; + } + + ul { + margin: 0; + padding: 0; + list-style: none; + + ul { + display: none; + margin-left: 1rem; + } + } + + a { + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } + + @media (min-width: $canvas-large) { + margin-bottom: 0; + + .content-wrapper { + position: fixed; + } + + ul ul { + display: block; + } + } +} + +// Footer +.page-footer { + padding: get-gutter(); + text-align: center; + color: $color-bg; + background-color: $color-primary; + + p { + margin: 0 auto; + max-width: $canvas-limit; + } + + a { + text-decoration: underline; + color: $color-bg; + } +} + +// Message types +.message-info { + margin-bottom: get-gutter(); + padding: 1rem; + border: 2px dashed $color-grey; + + &:last-child { + margin-bottom: 0; + } + + > :first-child { + margin-top: 0; + } + + > :last-child { + margin-bottom: 0; + } +} + +// Background colors and margins for the sample grids +.sample { + margin-bottom: get-gutter(); + padding: 1rem; + border: 1px solid $color-grey; + text-align: center; + list-style: none; + + > * { + margin-bottom: get-gutter(); + padding: get-gutter(); + background: $color-grey; + + &:last-child { + margin-bottom: 0; + } + + @media (min-width: $canvas-small) { + margin-bottom: 0; + } + } +} + +// Code samples +@media (min-width: $canvas-small) { + // Percentage-based columns + .simple-percents { + @include row(25% 25% 50%); + } + + // Traditional "x of 12" columns grid syntax + .x-of-y { + @include row(200%/12 400%/12 600%/12); + } + + // The "Holy Grail" layout (see http://alistapart.com/article/holygrail) + .holy-grail { + @include row(200px 100% 200px); + } + + // Nested rows + .sample-parent { + @include row(25% 75%); + } + + .sample-nested { + @include row(5em 100%); + + > * { + background-color: $color-grey-light; + } + } + + // Use the justify-content property to center columns (flexbox only) + .simple-center { + // Note: The use of non-percentage units in the row() mixin triggers flexbox + @include row(15rem 15rem); + justify-content: center; + } + + // Use the order property to reorder columns (flexbox only) + .simple-reorder { + @include row(100%/3 100%/3 100%/3, $layout: flexbox); + @include column-order(3 1 2); + } + + // Display arbitrary number of elements in a "gallery" grid + .list-gallery { + @include gallery(3); + } + + // Display all columns in a single row + .list-equal-cols { + @include equal-columns($layout: flexbox); + } +}