├── .bowerrc
├── .editorconfig
├── .gitignore
├── .jshintrc
├── .yo-rc.json
├── README.md
├── bower.json
├── e2e
├── main.po.js
└── main.spec.js
├── gulp
├── build.js
├── e2e-tests.js
├── inject.js
├── markups.js
├── proxy.js
├── server.js
├── styles.js
├── unit-tests.js
└── watch.js
├── gulpfile.js
├── karma.conf.js
├── package.json
├── protractor.conf.js
└── src
├── 404.html
├── app
├── index.js
├── main
│ ├── main.controller.js
│ ├── main.jade
│ └── partials
│ │ └── mixins.jade
└── styles
│ ├── index.scss
│ └── partials
│ ├── _controls.scss
│ ├── _diagram.scss
│ ├── _global_layout.scss
│ ├── _mixins.scss
│ ├── _reset.scss
│ └── _variables.scss
├── favicon.ico
├── index.html
└── tests
└── main.controller.spec.js
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "bower_components"
3 | }
4 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | bower_components/
3 | .sass-cache/
4 | .tmp/
5 | dist/
6 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "esnext": true,
4 | "bitwise": true,
5 | "camelcase": true,
6 | "curly": true,
7 | "eqeqeq": true,
8 | "immed": true,
9 | "indent": 2,
10 | "latedef": true,
11 | "newcap": true,
12 | "noarg": true,
13 | "quotmark": "single",
14 | "regexp": true,
15 | "undef": true,
16 | "unused": true,
17 | "strict": true,
18 | "trailing": true,
19 | "smarttabs": true,
20 | "white": true,
21 | "validthis": true,
22 | "globals": {
23 | "angular": false,
24 | // Angular Mocks
25 | "inject": false,
26 | // JASMINE
27 | "describe": false,
28 | "it": false,
29 | "before": false,
30 | "beforeEach": false,
31 | "after": false,
32 | "afterEach": false,
33 | "expect": false
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/.yo-rc.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator-gulp-angular": {
3 | "props": {
4 | "paths": {
5 | "src": "src",
6 | "dist": "dist",
7 | "e2e": "e2e",
8 | "tmp": ".tmp"
9 | },
10 | "angularVersion": "~1.3.4",
11 | "angularModules": [
12 | {
13 | "name": "angular-animate",
14 | "module": "ngAnimate"
15 | },
16 | {
17 | "name": "angular-sanitize",
18 | "module": "ngSanitize"
19 | }
20 | ],
21 | "jQuery": {
22 | "name": null,
23 | "version": null
24 | },
25 | "resource": {
26 | "name": null,
27 | "version": null,
28 | "module": null
29 | },
30 | "router": {
31 | "name": "angular-ui-router",
32 | "version": "~0.2.13",
33 | "module": "ui.router"
34 | },
35 | "ui": {
36 | "key": "none",
37 | "name": null,
38 | "version": null,
39 | "module": null
40 | },
41 | "cssPreprocessor": {
42 | "key": "ruby-sass",
43 | "extension": "scss",
44 | "module": "gulp-ruby-sass",
45 | "version": "~0.7.1"
46 | },
47 | "jsPreprocessor": {
48 | "key": "none",
49 | "extension": "js",
50 | "srcExtension": "js",
51 | "module": null,
52 | "version": null
53 | },
54 | "htmlPreprocessor": {
55 | "key": "jade",
56 | "extension": "jade",
57 | "module": "jade",
58 | "version": "~1.8.1"
59 | },
60 | "bootstrapComponents": {
61 | "name": null,
62 | "version": null,
63 | "key": null,
64 | "module": null
65 | },
66 | "foundationComponents": {
67 | "name": null,
68 | "version": null,
69 | "key": null,
70 | "module": null
71 | }
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ##Learning Box Model: `box-sizing`
2 |
3 |
4 |
5 |
6 | ###Run/Develop:
7 |
8 | #### Requirements:
9 | - bower, gulp, sass (ruby)
10 |
11 | ```
12 | npm install -g bower gulp
13 | gem install sass
14 | ```
15 |
16 | #### Setup
17 | 1. Clone Repo
18 | 2. Install node modules and bower components / dependencies
19 | ```
20 | npm install && bower install
21 | ```
22 | 3. Run
23 | ```
24 | gulp serve
25 | ```
26 |
27 |
28 | TODO:
29 | - Unit Tests
30 | - ~Add/Remove margin from calculated size~
31 | - Responsive Styles
32 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cssBoxModel",
3 | "version": "0.0.0",
4 | "dependencies": {
5 | "angular-animate": "~1.3.4",
6 | "angular-sanitize": "~1.3.4",
7 | "angular-ui-router": "~0.2.13",
8 | "angular": "~1.3.4",
9 | "neat": "~1.7.2",
10 | "angular-slider": "~0.2.14"
11 | },
12 | "devDependencies": {
13 | "angular-mocks": "~1.3.4"
14 | },
15 | "resolutions": {
16 | "angular": "~1.3.4"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/e2e/main.po.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This file uses the Page Object pattern to define the main page for tests
3 | * https://docs.google.com/presentation/d/1B6manhG0zEXkC-H-tPo2vwU06JhL8w9-XCF9oehXzAQ
4 | */
5 |
6 | 'use strict';
7 |
8 | var MainPage = function() {
9 | //TODO
10 | };
11 |
12 | module.exports = new MainPage();
13 |
--------------------------------------------------------------------------------
/e2e/main.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('The main view', function () {
4 | var page;
5 |
6 | //TODO
7 |
8 | });
9 |
--------------------------------------------------------------------------------
/gulp/build.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var paths = gulp.paths;
6 |
7 | var $ = require('gulp-load-plugins')({
8 | pattern: ['gulp-*', 'main-bower-files', 'uglify-save-license', 'del']
9 | });
10 |
11 | gulp.task('partials', ['markups'], function () {
12 | return gulp.src([
13 | paths.src + '/app/**/*.html',
14 | paths.tmp + '/app/**/*.html'
15 | ])
16 | .pipe($.minifyHtml({
17 | empty: true,
18 | spare: true,
19 | quotes: true
20 | }))
21 | .pipe($.angularTemplatecache('templateCacheHtml.js', {
22 | module: 'cssBoxModel'
23 | }))
24 | .pipe(gulp.dest(paths.tmp + '/partials/'));
25 | });
26 |
27 | gulp.task('html', ['inject', 'partials'], function () {
28 | var partialsInjectFile = gulp.src(paths.tmp + '/partials/templateCacheHtml.js', { read: false });
29 | var partialsInjectOptions = {
30 | starttag: '',
31 | ignorePath: paths.tmp + '/partials',
32 | addRootSlash: false
33 | };
34 |
35 | var htmlFilter = $.filter('*.html');
36 | var jsFilter = $.filter('**/*.js');
37 | var cssFilter = $.filter('**/*.css');
38 | var assets;
39 |
40 | return gulp.src(paths.tmp + '/serve/*.html')
41 | .pipe($.inject(partialsInjectFile, partialsInjectOptions))
42 | .pipe(assets = $.useref.assets())
43 | .pipe($.rev())
44 | .pipe(jsFilter)
45 | .pipe($.ngAnnotate())
46 | .pipe($.uglify({preserveComments: $.uglifySaveLicense}))
47 | .pipe(jsFilter.restore())
48 | .pipe(cssFilter)
49 | .pipe($.csso())
50 | .pipe(cssFilter.restore())
51 | .pipe(assets.restore())
52 | .pipe($.useref())
53 | .pipe($.revReplace())
54 | .pipe(htmlFilter)
55 | .pipe($.minifyHtml({
56 | empty: true,
57 | spare: true,
58 | quotes: true
59 | }))
60 | .pipe(htmlFilter.restore())
61 | .pipe(gulp.dest(paths.dist + '/'))
62 | .pipe($.size({ title: paths.dist + '/', showFiles: true }));
63 | });
64 |
65 | // gulp.task('images', function () {
66 | // return gulp.src(paths.src + '/assets/images/**/*')
67 | // .pipe(gulp.dest(paths.dist + '/assets/images/'));
68 | // });
69 |
70 | gulp.task('fonts', function () {
71 | return gulp.src($.mainBowerFiles())
72 | .pipe($.filter('**/*.{eot,svg,ttf,woff}'))
73 | .pipe($.flatten())
74 | .pipe(gulp.dest(paths.dist + '/fonts/'));
75 | });
76 |
77 | gulp.task('misc', function () {
78 | return gulp.src(paths.src + '/**/*.ico')
79 | .pipe(gulp.dest(paths.dist + '/'));
80 | });
81 |
82 | gulp.task('clean', function (done) {
83 | $.del([paths.dist + '/', paths.tmp + '/'], done);
84 | });
85 |
86 | //removed images b/c have none currently
87 | gulp.task('build', ['html', 'fonts', 'misc']);
88 |
--------------------------------------------------------------------------------
/gulp/e2e-tests.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var $ = require('gulp-load-plugins')();
6 |
7 | var browserSync = require('browser-sync');
8 |
9 | var paths = gulp.paths;
10 |
11 | // Downloads the selenium webdriver
12 | gulp.task('webdriver-update', $.protractor.webdriver_update);
13 |
14 | gulp.task('webdriver-standalone', $.protractor.webdriver_standalone);
15 |
16 | function runProtractor (done) {
17 |
18 | gulp.src(paths.e2e + '/**/*.js')
19 | .pipe($.protractor.protractor({
20 | configFile: 'protractor.conf.js',
21 | }))
22 | .on('error', function (err) {
23 | // Make sure failed tests cause gulp to exit non-zero
24 | throw err;
25 | })
26 | .on('end', function () {
27 | // Close browser sync server
28 | browserSync.exit();
29 | done();
30 | });
31 | }
32 |
33 | gulp.task('protractor', ['protractor:src']);
34 | gulp.task('protractor:src', ['serve:e2e', 'webdriver-update'], runProtractor);
35 | gulp.task('protractor:dist', ['serve:e2e-dist', 'webdriver-update'], runProtractor);
36 |
--------------------------------------------------------------------------------
/gulp/inject.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var paths = gulp.paths;
6 |
7 | var $ = require('gulp-load-plugins')();
8 |
9 | var wiredep = require('wiredep').stream;
10 |
11 | gulp.task('inject', ['styles'], function () {
12 |
13 | var injectStyles = gulp.src([
14 | paths.tmp + '/serve/app/**/*.css',
15 | '!' + paths.tmp + '/serve/app/vendor.css'
16 | ], { read: false });
17 |
18 | var injectScripts = gulp.src([
19 | paths.src + '/app/**/*.js',
20 | '!' + paths.src + '/app/**/*.spec.js',
21 | '!' + paths.src + '/app/**/*.mock.js'
22 | ]).pipe($.angularFilesort());
23 |
24 | var injectOptions = {
25 | ignorePath: [paths.src, paths.tmp + '/serve'],
26 | addRootSlash: false
27 | };
28 |
29 | var wiredepOptions = {
30 | directory: 'bower_components'
31 | };
32 |
33 | return gulp.src(paths.src + '/*.html')
34 | .pipe($.inject(injectStyles, injectOptions))
35 | .pipe($.inject(injectScripts, injectOptions))
36 | .pipe(wiredep(wiredepOptions))
37 | .pipe(gulp.dest(paths.tmp + '/serve'));
38 |
39 | });
40 |
--------------------------------------------------------------------------------
/gulp/markups.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var paths = gulp.paths;
6 |
7 | var $ = require('gulp-load-plugins')();
8 |
9 | gulp.task('markups', function() {
10 | function renameToHtml(path) {
11 | path.extname = '.html';
12 | }
13 |
14 | return gulp.src(paths.src + '/{app,components}/**/*.jade')
15 | .pipe($.consolidate('jade', { pretty: ' ' }))
16 | .on('error', function handleError(err) {
17 | console.error(err.toString());
18 | this.emit('end');
19 | })
20 | .pipe($.rename(renameToHtml))
21 | .pipe(gulp.dest(paths.tmp + '/serve/'));
22 | });
23 |
--------------------------------------------------------------------------------
/gulp/proxy.js:
--------------------------------------------------------------------------------
1 | /*jshint unused:false */
2 |
3 | /***************
4 |
5 | This file allow to configure a proxy system plugged into BrowserSync
6 | in order to redirect backend requests while still serving and watching
7 | files from the web project
8 |
9 | IMPORTANT: The proxy is disabled by default.
10 |
11 | If you want to enable it, watch at the configuration options and finally
12 | change the `module.exports` at the end of the file
13 |
14 | ***************/
15 |
16 | 'use strict';
17 |
18 | var httpProxy = require('http-proxy');
19 | var chalk = require('chalk');
20 |
21 | /*
22 | * Location of your backend server
23 | */
24 | var proxyTarget = 'http://server/context/';
25 |
26 | var proxy = httpProxy.createProxyServer({
27 | target: proxyTarget
28 | });
29 |
30 | proxy.on('error', function(error, req, res) {
31 | res.writeHead(500, {
32 | 'Content-Type': 'text/plain'
33 | });
34 |
35 | console.error(chalk.red('[Proxy]'), error);
36 | });
37 |
38 | /*
39 | * The proxy middleware is an Express middleware added to BrowserSync to
40 | * handle backend request and proxy them to your backend.
41 | */
42 | function proxyMiddleware(req, res, next) {
43 | /*
44 | * This test is the switch of each request to determine if the request is
45 | * for a static file to be handled by BrowserSync or a backend request to proxy.
46 | *
47 | * The existing test is a standard check on the files extensions but it may fail
48 | * for your needs. If you can, you could also check on a context in the url which
49 | * may be more reliable but can't be generic.
50 | */
51 | if (/\.(html|css|js|png|jpg|jpeg|gif|ico|xml|rss|txt|eot|svg|ttf|woff|cur)(\?((r|v|rel|rev)=[\-\.\w]*)?)?$/.test(req.url)) {
52 | next();
53 | } else {
54 | proxy.web(req, res);
55 | }
56 | }
57 |
58 | /*
59 | * This is where you activate or not your proxy.
60 | *
61 | * The first line activate if and the second one ignored it
62 | */
63 |
64 | //module.exports = [proxyMiddleware];
65 | module.exports = [];
66 |
--------------------------------------------------------------------------------
/gulp/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var paths = gulp.paths;
6 |
7 | var util = require('util');
8 |
9 | var browserSync = require('browser-sync');
10 |
11 | var middleware = require('./proxy');
12 |
13 | function browserSyncInit(baseDir, files, browser) {
14 | browser = browser === undefined ? 'default' : browser;
15 |
16 | var routes = null;
17 | if(baseDir === paths.src || (util.isArray(baseDir) && baseDir.indexOf(paths.src) !== -1)) {
18 | routes = {
19 | '/bower_components': 'bower_components'
20 | };
21 | }
22 |
23 | browserSync.instance = browserSync.init(files, {
24 | startPath: '/',
25 | server: {
26 | baseDir: baseDir,
27 | middleware: middleware,
28 | routes: routes
29 | },
30 | browser: browser
31 | });
32 | }
33 |
34 | gulp.task('serve', ['watch'], function () {
35 | browserSyncInit([
36 | paths.tmp + '/serve',
37 | paths.src
38 | ], [
39 | paths.tmp + '/serve/app/**/*.css',
40 | paths.src + '/app/**/*.js',
41 | // paths.src + 'src/assets/images/**/*',
42 | paths.tmp + '/serve/*.html',
43 | paths.tmp + '/serve/app/**/*.html',
44 | paths.src + '/app/**/*.html'
45 | ]);
46 | });
47 |
48 | gulp.task('serve:dist', ['build'], function () {
49 | browserSyncInit(paths.dist);
50 | });
51 |
52 | gulp.task('serve:e2e', ['inject'], function () {
53 | browserSyncInit([paths.tmp + '/serve', paths.src], null, []);
54 | });
55 |
56 | gulp.task('serve:e2e-dist', ['build'], function () {
57 | browserSyncInit(paths.dist, null, []);
58 | });
59 |
--------------------------------------------------------------------------------
/gulp/styles.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var paths = gulp.paths;
6 |
7 | var $ = require('gulp-load-plugins')();
8 |
9 | gulp.task('styles', function () {
10 |
11 | var sassOptions = {
12 | style: 'expanded'
13 | };
14 |
15 | var injectFiles = gulp.src([
16 | paths.src + '/app/styles/**/*.scss',
17 | '!' + paths.src + '/app/styles/index.scss',
18 | '!' + paths.src + '/app/styles/vendor.scss',
19 | '!' + paths.src + '/app/styles/partials/**/*.scss'
20 | ], { read: false });
21 |
22 | var injectOptions = {
23 | transform: function(filePath) {
24 | filePath = filePath.replace(paths.src + '/app/styles/', '');
25 | // filePath = filePath.replace(paths.src + '/components/', '../components/');
26 | return '@import \'' + filePath + '\';';
27 | },
28 | starttag: '// injector',
29 | endtag: '// endinjector',
30 | addRootSlash: false
31 | };
32 |
33 | var indexFilter = $.filter('index.scss');
34 |
35 | return gulp.src([
36 | paths.src + '/app/styles/index.scss',
37 | paths.src + '/app/styles/vendor.scss'
38 | ])
39 | .pipe(indexFilter)
40 | .pipe($.inject(injectFiles, injectOptions))
41 | .pipe(indexFilter.restore())
42 | .pipe($.rubySass(sassOptions))
43 |
44 | .pipe($.autoprefixer())
45 | .on('error', function handleError(err) {
46 | console.error(err.toString());
47 | this.emit('end');
48 | })
49 | .pipe(gulp.dest(paths.tmp + '/serve/app/'));
50 | });
51 |
--------------------------------------------------------------------------------
/gulp/unit-tests.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var $ = require('gulp-load-plugins')();
6 |
7 | var wiredep = require('wiredep');
8 |
9 | var paths = gulp.paths;
10 |
11 | function runTests(singleRun, done) {
12 | var bowerDeps = wiredep({
13 | directory: 'bower_components',
14 | dependencies: true,
15 | devDependencies: true
16 | });
17 |
18 | var testFiles = bowerDeps.js.concat([
19 | paths.src + '/{app,components,tests}/**/*.js'
20 | ]);
21 |
22 | gulp.src(testFiles)
23 | .pipe($.karma({
24 | configFile: 'karma.conf.js',
25 | action: (singleRun) ? 'run' : 'watch'
26 | }))
27 | .on('error', function (err) {
28 | // Make sure failed tests cause gulp to exit non-zero
29 | throw err;
30 | });
31 | }
32 |
33 | gulp.task('test', function (done) {
34 | runTests(true /* singleRun */ , done)
35 | });
36 | gulp.task('test:auto', function (done) {
37 | runTests(false /* singleRun */ , done)
38 | });
39 |
--------------------------------------------------------------------------------
/gulp/watch.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var paths = gulp.paths;
6 |
7 | gulp.task('watch', ['markups', 'inject'], function () {
8 | gulp.watch([
9 | paths.src + '/*.html',
10 | paths.src + '/app/styles/**/*.scss',
11 | paths.src + '/app/**/*.js',
12 | 'bower.json'
13 | ], ['inject']);
14 | gulp.watch(paths.src + '/app/main/**/*.jade', ['markups']);
15 | });
16 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | gulp.paths = {
6 | src: 'src',
7 | dist: 'dist',
8 | tmp: '.tmp',
9 | e2e: 'e2e'
10 | };
11 |
12 | require('require-dir')('./gulp');
13 |
14 | gulp.task('default', ['clean'], function () {
15 | gulp.start('build');
16 | });
17 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function (config) {
4 |
5 | config.set({
6 | color: true,
7 | frameworks: ['jasmine'],
8 |
9 | browsers: ['PhantomJS'],
10 |
11 | plugins: [
12 | 'karma-phantomjs-launcher',
13 | 'karma-jasmine'
14 | ]
15 | });
16 | };
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cssBoxModel",
3 | "version": "0.0.0",
4 | "dependencies": {},
5 | "devDependencies": {
6 | "gulp": "~3.8.10",
7 | "gulp-autoprefixer": "~2.0.0",
8 | "gulp-angular-templatecache": "~1.4.2",
9 | "del": "~0.1.3",
10 | "gulp-consolidate": "~0.1.2",
11 | "gulp-csso": "~0.2.9",
12 | "gulp-filter": "~1.0.2",
13 | "gulp-flatten": "~0.0.4",
14 | "gulp-jshint": "~1.9.0",
15 | "gulp-load-plugins": "~0.7.1",
16 | "gulp-size": "~1.1.0",
17 | "gulp-uglify": "~1.0.1",
18 | "gulp-useref": "~1.0.2",
19 | "gulp-ng-annotate": "^0.5.0",
20 | "gulp-replace": "~0.5.0",
21 | "gulp-rename": "~1.2.0",
22 | "gulp-rev": "~2.0.1",
23 | "gulp-rev-replace": "~0.3.1",
24 | "gulp-minify-html": "~0.1.7",
25 | "gulp-inject": "~1.0.2",
26 | "gulp-protractor": "~0.0.11",
27 | "gulp-karma": "~0.0.4",
28 | "gulp-ruby-sass": "~0.7.1",
29 | "gulp-angular-filesort": "~1.0.4",
30 | "jade": "~1.8.1",
31 | "main-bower-files": "~2.4.0",
32 | "jshint-stylish": "~1.0.0",
33 | "wiredep": "~2.2.0",
34 | "karma-jasmine": "~0.3.1",
35 | "karma-phantomjs-launcher": "~0.1.4",
36 | "require-dir": "~0.1.0",
37 | "browser-sync": "~1.7.1",
38 | "http-proxy": "~1.7.0",
39 | "chalk": "~0.5.1",
40 | "protractor": "~1.4.0",
41 | "uglify-save-license": "~0.4.1"
42 | },
43 | "engines": {
44 | "node": ">=0.10.0"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/protractor.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var paths = require('./.yo-rc.json')['generator-gulp-angular'].props.paths;
4 |
5 | // An example configuration file.
6 | exports.config = {
7 | // The address of a running selenium server.
8 | //seleniumAddress: 'http://localhost:4444/wd/hub',
9 | //seleniumServerJar: deprecated, this should be set on node_modules/protractor/config.json
10 |
11 | // Capabilities to be passed to the webdriver instance.
12 | capabilities: {
13 | 'browserName': 'chrome'
14 | },
15 |
16 | // Spec patterns are relative to the current working directly when
17 | // protractor is called.
18 | specs: [paths.e2e + '/**/*.js'],
19 |
20 | // Options to be passed to Jasmine-node.
21 | jasmineNodeOpts: {
22 | showColors: true,
23 | defaultTimeoutInterval: 30000
24 | }
25 | };
26 |
--------------------------------------------------------------------------------
/src/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Page Not Found :(
6 |
141 |
142 |
143 |
144 |
Not found :(
145 |
Sorry, but the page you were trying to view does not exist.
146 |
It looks like this was the result of either:
147 |
148 | - a mistyped address
149 | - an out-of-date link
150 |
151 |
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/src/app/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('cssBoxModel', ['ngAnimate', 'ngSanitize', 'ui.router','ui.slider'])
4 |
5 | .config(function($stateProvider, $urlRouterProvider) {
6 | $stateProvider
7 | .state('home', {
8 | url: '/',
9 | templateUrl: 'app/main/main.html',
10 | controller: 'MainCtrl'
11 | });
12 |
13 | $urlRouterProvider.otherwise('/');
14 | })
15 |
16 | .directive('labelPositionV', function() {
17 | return {
18 | restrict: 'AE',
19 | scope: {},
20 | link: function(scope, element, attrs, ctrl) {
21 | var id = attrs.id;
22 | attrs.$observe('labelPositionTop', function(value) {
23 | var styleTop = "";
24 | angular.element(document).find('head').append(styleTop);
25 | });
26 | attrs.$observe('labelPositionBottom', function(value) {
27 | var styleBottom = "";
28 | angular.element(document).find('head').append(styleBottom);
29 | });
30 | }
31 | };
32 | })
33 |
34 | .directive('labelPositionH', function() {
35 | return {
36 | restrict: 'AE',
37 | scope: {},
38 | link: function(scope, element, attrs, ctrl) {
39 | var id = attrs.id;
40 | attrs.$observe('labelPositionRight', function(value) {
41 | var styleRight = "";
42 | angular.element(document).find('head').append(styleRight);
43 | });
44 | attrs.$observe('labelPositionLeft', function(value) {
45 | var styleLeft = "";
46 | angular.element(document).find('head').append(styleLeft);
47 | });
48 |
49 | }
50 | };
51 | });
52 |
--------------------------------------------------------------------------------
/src/app/main/main.controller.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var app = angular.module('cssBoxModel');
3 |
4 | app.controller('MainCtrl', function ($scope) {
5 |
6 | //models: default adjustable values
7 | $scope.padding = {
8 | top: 20,
9 | right: 20,
10 | bottom: 20,
11 | left: 20,
12 | v: function () {
13 | return this.top + this.bottom;
14 | },
15 | h: function () {
16 | return this.right + this.left;
17 | }
18 | };
19 |
20 | $scope.border = {
21 | top: 15,
22 | right: 15,
23 | bottom: 15,
24 | left: 15,
25 | v: function () {
26 | return this.top + this.bottom;
27 | },
28 | h: function () {
29 | return this.right + this.left;
30 | }
31 | };
32 |
33 | $scope.margin = {
34 | top: 20,
35 | right: 20,
36 | bottom: 20,
37 | left: 20,
38 | v: function () {
39 | return this.top + this.bottom;
40 | },
41 | h: function () {
42 | return this.right + this.left;
43 | }
44 | };
45 |
46 | $scope.box = {
47 | sizing: 'content-box'
48 | };
49 |
50 | $scope.dimensions = {
51 | width: 220,
52 | height: 220
53 | };
54 |
55 | $scope.innerContent = {
56 | width: getInnerWidth(),
57 | height: getInnerHeight()
58 | };
59 |
60 | $scope.generatedIncludeMargin = false;
61 |
62 | $scope.generatedBoxDimensions = {
63 | width: getGeneratedBoxDimensionsWidth(),
64 | height: getGeneratedBoxDimensionsHeight()
65 | };
66 |
67 | $scope.checkIncludeMargin = function() {
68 | $scope.generatedBoxDimensions.width = getGeneratedBoxDimensionsWidth();
69 | $scope.generatedBoxDimensions.height = getGeneratedBoxDimensionsHeight();
70 | };
71 |
72 |
73 | //actual applied style values
74 | $scope.boxPosition = {
75 | left: 50,
76 | top: 56
77 | };
78 |
79 | $scope.styleMargin = {
80 | width: 300,
81 | height: 300,
82 | top: -50,
83 | left: -50
84 | };
85 |
86 | $scope.styleBorder = {
87 | width: 260,
88 | height: 260,
89 | top: -30,
90 | left: -30
91 | };
92 |
93 | $scope.stylePadding = {
94 | width: 242,
95 | height: 242,
96 | top: -20,
97 | left: -20
98 | };
99 |
100 | //watch for changes applied to sliders and calculate rendered styles
101 | $scope.$watch(function () {
102 | $scope.boxPosition.top = calcBoxPositionTop() + 6;
103 | $scope.boxPosition.left = calcBoxPositionLeft();
104 |
105 | //Margin Styles
106 | $scope.styleMargin.width = $scope.margin.h() + $scope.styleBorder.width;
107 | $scope.styleMargin.height = $scope.margin.v() + $scope.styleBorder.height;
108 | $scope.styleMargin.top = -calcBoxPositionTop();
109 | $scope.styleMargin.left = -calcBoxPositionLeft();
110 |
111 | //Border Styles
112 | $scope.styleBorder.width = $scope.border.h() + $scope.stylePadding.width;
113 | $scope.styleBorder.height = $scope.border.v() + $scope.stylePadding.height;
114 | $scope.styleBorder.top = -($scope.border.top + $scope.padding.top);
115 | $scope.styleBorder.left = -($scope.border.left + $scope.padding.left);
116 |
117 | //Padding Styles
118 | $scope.stylePadding.width = $scope.padding.h() + getInnerWidth() + 2;
119 | $scope.stylePadding.height = $scope.padding.v() + getInnerHeight() + 2;
120 | $scope.stylePadding.top = -$scope.padding.top;
121 | $scope.stylePadding.left = -$scope.padding.left;
122 |
123 | //Inner Content Styles- based on box-sizing
124 | $scope.innerContent.width = getInnerWidth();
125 | $scope.innerContent.height = getInnerHeight();
126 |
127 | //Generated Dimensions- based on box-sizing
128 | $scope.generatedBoxDimensions.width = getGeneratedBoxDimensionsWidth();
129 | $scope.generatedBoxDimensions.height = getGeneratedBoxDimensionsHeight();
130 | });
131 |
132 | function getInnerWidth() {
133 | var width;
134 | if ($scope.box.sizing === 'border-box') {
135 | width = $scope.dimensions.width -
136 | $scope.border.h() -
137 | $scope.padding.h();
138 | } else {
139 | width = $scope.dimensions.width;
140 | }
141 | return (width > 0) ? width : 0;
142 | }
143 |
144 | function getInnerHeight() {
145 | var height;
146 | if ($scope.box.sizing === 'border-box') {
147 | height = $scope.dimensions.height -
148 | $scope.border.v() -
149 | $scope.padding.v();
150 | } else {
151 | height = $scope.dimensions.height;
152 | }
153 | return (height > 0) ? height : 0;
154 | }
155 |
156 |
157 | //if padding + border > dimension, return (padding + border - dimension) [+ margin]
158 | function getGeneratedBoxDimensionsWidth() {
159 | var width;
160 | if ($scope.box.sizing === 'border-box') {
161 | width = (getInnerWidth() === 0) ? calcPaddingBorderWidth() : $scope.dimensions.width;
162 | } else {
163 | width = $scope.dimensions.width + calcPaddingBorderWidth();
164 | }
165 | return ($scope.generatedIncludeMargin) ? width + $scope.margin.h() : width;
166 | }
167 |
168 | function getGeneratedBoxDimensionsHeight() {
169 | var height;
170 | if ($scope.box.sizing === 'border-box') {
171 | height = (getInnerHeight() === 0) ? calcPaddingBorderHeight() : $scope.dimensions.height;
172 | } else {
173 | height = $scope.dimensions.height + calcPaddingBorderHeight();
174 | }
175 | return ($scope.generatedIncludeMargin) ? height + $scope.margin.v() : height;
176 | }
177 |
178 | /*
179 | * Private: Helpers
180 | */
181 | function calcBoxPositionTop() {
182 | return $scope.margin.top + $scope.border.top + $scope.padding.top;
183 | }
184 |
185 | function calcBoxPositionLeft() {
186 | return $scope.margin.left + $scope.border.left + $scope.padding.left;
187 | }
188 |
189 | function calcPaddingBorderWidth() {
190 | return $scope.padding.h() + $scope.border.h();
191 | }
192 |
193 | function calcPaddingBorderHeight() {
194 | return $scope.padding.v() + $scope.border.v();
195 | }
196 |
197 | });
198 |
--------------------------------------------------------------------------------
/src/app/main/main.jade:
--------------------------------------------------------------------------------
1 | include partials/mixins
2 |
3 | main
4 | section.controls
5 | div.control-set#box-sizing
6 | fieldset
7 | legend#bs box-sizing
8 | label
9 | input(type="radio", ng-model="box.sizing", value="content-box" class="radio")
10 | | content-box
11 | label
12 | input(type="radio", ng-model="box.sizing", value="border-box" class="radio")
13 | | border-box
14 |
15 | //- extract to mixin?
16 | //- meh, maybe no
17 | each attr in ["padding","border","margin"]
18 | div.control-set(id=attr)
19 | fieldset
20 | legend= attr
21 | .sliders
22 | each val in ["top", "right", "bottom", "left"]
23 | label #{attr}-#{val}
24 | slider(floor="0" ceiling="120" step="5" precision="1" ng-model="#{attr}.#{val}" highlight="left")
25 | div.value {{#{attr}.#{val}}}px
26 |
27 | section.box-model
28 | div.control-set#content
29 | fieldset
30 | legend Dimensions
31 | .sliders
32 | label width
33 | slider(floor="0" ceiling="400" step="10" precision="1" ng-model="dimensions.width" highlight="left")
34 | div.value {{dimensions.width}}px
35 | label height
36 | slider(floor="0" ceiling="400" step="10" precision="1" ng-model="dimensions.height" highlight="left")
37 | div.value {{dimensions.height}}px
38 | div.control-set#generated-size
39 | fieldset
40 | legend Generated Size
41 | input#toggle-include-margin.toggle(type="checkbox", checked="", ng-model="generatedIncludeMargin", ng-change="checkIncludeMargin()")
42 | label.toggle-control(for="toggle-include-margin")
43 | span.toggle-text include margin
44 | div.generated-width horizontal: {{generatedBoxDimensions.width}}px
45 | div.generated-height vertical: {{generatedBoxDimensions.height}}px
46 | div#diagram
47 | .box(ng-style="{'top': boxPosition.top+'px', 'left': boxPosition.left+'px', 'width': dimensions.width+'px', 'height': dimensions.height+'px'}")
48 | .box-margin.box-property(ng-style="{'width': styleMargin.width+'px', 'height': styleMargin.height+'px', 'top': styleMargin.top+'px', 'left': styleMargin.left+'px'}")
49 | span.property-label#property-label-margin margin
50 | span#margin-v.box-property-vertical(data-id="margin-v", data-top="{{margin.top}}", data-bottom="{{margin.bottom}}", label-position-top="{{margin.top}}", label-position-bottom="{{margin.bottom}}", label-position-v="")
51 | span#margin-h.box-property-horizontal(data-id="margin-h", data-left="{{margin.left}}", data-right="{{margin.right}}", label-position-right="{{margin.right}}", label-position-left="{{margin.left}}", label-position-h="")
52 | .box-border.box-property(ng-style="{'width': styleBorder.width+'px', 'height': styleBorder.height+'px', 'top': styleBorder.top+'px', 'left': styleBorder.left+'px'}")
53 | span.property-label#property-label-border border
54 | span#border-v.box-property-vertical(data-id="border-v", data-top="{{border.top}}", data-bottom="{{border.bottom}}", label-position-top="{{border.top}}", label-position-bottom="{{border.bottom}}", label-position-v="")
55 | span#border-h.box-property-horizontal(data-id="border-h", data-left="{{border.left}}", data-right="{{border.right}}", label-position-right="{{border.right}}", label-position-left="{{border.left}}", label-position-h="")
56 | .box-padding.box-property(ng-style="{'width': stylePadding.width+'px', 'height': stylePadding.height+'px', 'top': stylePadding.top+'px', 'left': stylePadding.left+'px'}")
57 | span.property-label#property-label-padding padding
58 | span#padding-v.box-property-vertical(data-id="padding-v", data-top="{{padding.top}}", data-bottom="{{padding.bottom}}", label-position-top="{{padding.top}}", label-position-bottom="{{padding.bottom}}", label-position-v="")
59 | span#padding-h.box-property-horizontal(data-id="padding-h", data-left="{{padding.left}}", data-right="{{padding.right}}", label-position-right="{{padding.right}}", label-position-left="{{padding.left}}", label-position-h="")
60 | .box-inner.box-property(ng-style="{'width': innerContent.width+'px', 'height': innerContent.height+'px'}", data-height="{{innerContent.height}}", data-width="{{innerContent.width}}")
61 | span.property-label#property-label-content content
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/src/app/main/partials/mixins.jade:
--------------------------------------------------------------------------------
1 | mixin controlset
2 | each attr in ["margin", "padding", "border"]
3 | div.control-set
4 | each val in ["top", "right", "bottom", "left"]
5 | label #{attr}-#{val}
6 | slider(ng-model="#{attr}.#{val}")
7 | div.value {{#{attr}.#{val}}}px
8 |
--------------------------------------------------------------------------------
/src/app/styles/index.scss:
--------------------------------------------------------------------------------
1 | @import "../../../bower_components/bourbon/app/assets/stylesheets/bourbon";
2 | @import "../../../bower_components/neat/app/assets/stylesheets/neat";
3 |
4 | @import "partials/reset";
5 | @import "partials/variables";
6 | @import "partials/mixins";
7 |
8 | @import "partials/global_layout";
9 | @import "partials/controls";
10 | @import "partials/diagram";
11 |
12 | // injector
13 | // endinjector
14 |
--------------------------------------------------------------------------------
/src/app/styles/partials/_controls.scss:
--------------------------------------------------------------------------------
1 | $color-margin: #DE6A63;
2 | $color-padding: #C5D936;
3 | $color-content: #63BCF8;
4 | $color-border: #F8CC63;
5 | $color-box-sizing: #8ADFE0;
6 |
7 | $color-bg: #242930;
8 | $color-dark-light: #343434;
9 | $color-dark-lighter: #444;
10 | $color-dark-lightest: #777;
11 | $color-body: #808386;
12 | $color-white: #FFFFFF;
13 |
14 |
15 | $knob-size: 20px;
16 | $knob-border-width: 3px;
17 |
18 | $boxes: (content: $color-content,
19 | padding: $color-padding,
20 | border: $color-border,
21 | margin: $color-margin,
22 | box-sizing: $color-box-sizing,
23 | generated-size: $color-content);
24 |
25 | $sliders: content, padding, border, margin;
26 |
27 |
28 | $lg: new-breakpoint(min-width 1245px 7);
29 | $md: new-breakpoint(min-width 950px);
30 | $sm: new-breakpoint(min-width 790px 6);
31 |
32 |
33 | /*****************************************
34 | * CONTROL STYLES
35 | ******************************************/
36 |
37 | // Fieldset/Legend
38 | // ---------------------------------------
39 |
40 | fieldset {
41 | border: 1px solid $color-dark-light;
42 | padding: 0 10px 5px;
43 | }
44 |
45 | #generated-size fieldset {
46 | min-height: 114px;
47 | }
48 |
49 | legend {
50 | text-transform: uppercase;
51 | font-weight: 300;
52 | font-size: 1.3em;
53 | }
54 |
55 | @each $property, $color in $boxes {
56 | ##{$property} {
57 | legend {
58 | color: $color;
59 | }
60 | }
61 | }
62 |
63 | label, .value, .toggle-text {
64 | font-size: 60%;
65 | display: inline-block;
66 | white-space: nowrap;
67 | font-family: unquote(map-get($bodytype, font-family));
68 | letter-spacing: 1.5px;
69 | }
70 |
71 | .control-set {
72 | margin-top: 20px;
73 | width: 100%;
74 | label, .toggle-text {
75 | width: 25%;
76 | text-transform: uppercase;
77 | }
78 | .slider {
79 | width: 65%;
80 | @include media($md) {
81 | width: 55%;
82 | }
83 | @include media($lg) {
84 | width: 63%;
85 | }
86 | }
87 | .value {
88 | width: 7%;
89 | text-align: right;
90 | }
91 | }
92 |
93 | .box-model #content label {
94 | width: 25%;
95 | @include media($md) {
96 | width: 22%;
97 | }
98 | }
99 |
100 | #box-sizing label {
101 | width: 40%;
102 | }
103 |
104 |
105 |
106 | // Radio Button
107 | // ---------------------------------------
108 | .radio {
109 | position: relative;
110 | margin: 0 1rem 0 0;
111 | cursor: pointer;
112 | &::before,
113 | &::after {
114 | @include transition(all 0.3s ease-in-out);
115 | content: "";
116 | position: absolute;
117 | top: -0.2rem;
118 | left: -0.2rem;
119 | z-index: 1;
120 | width: $knob-size;
121 | height: $knob-size;
122 | background: $color-dark-light !important;
123 | border-radius: 50%;
124 | }
125 | &:checked,
126 | &.ng-valid-parse {
127 | &::before {
128 | @include transform(scale(0, 0));
129 | border-color: $color-box-sizing !important;
130 | border-width: $knob-border-width !important;
131 | }
132 | &::after {
133 | border: $knob-border-width solid $color-box-sizing !important;
134 | background: $color-bg !important;
135 | }
136 | }
137 | }
138 |
139 | // Range Sliders
140 | // ---------------------------------------
141 | slider, [slider] {
142 | display: inline-block;
143 | position: relative;
144 | height: 7px;
145 | width: 63%;
146 | vertical-align: middle;
147 | margin: 5px;
148 | div {
149 | white-space: nowrap;
150 | position: absolute;
151 | &.handle {
152 | border: $knob-border-width solid;
153 | cursor: pointer;
154 | width: $knob-size;
155 | height: $knob-size;
156 | top: -8px;
157 | background-color: $color-bg;
158 | z-index: 2;
159 | border-radius: 100%;
160 | &::after {
161 | content: '';
162 | width: 8px;
163 | height: 8px;
164 | position: absolute;
165 | left: 6px;
166 | border-radius: 100%;
167 | background-color: transparent;
168 | }
169 | &.active::after {
170 | background-color: transparent;
171 | }
172 | }
173 | &.bar {
174 | width: 100%;
175 | height: 100%;
176 | border-radius: 7px;
177 | background: $color-dark-lighter;
178 | overflow: hidden;
179 | .selection {
180 | width: 0;
181 | height: 100%;
182 | }
183 | }
184 | // TODO: remove Bubble functionality from slider directive
185 | &.bubble {
186 | display: none;
187 | cursor: default;
188 | top: -22px;
189 | padding: 1px 3px;
190 | font-size: 0.7em;
191 | &.active {
192 | display: inline-block;
193 | }
194 | &.limit {
195 | color: $color-dark-lightest;
196 | }
197 | }
198 | }
199 | }
200 |
201 | .bubble.value.low.ng-binding.active {
202 | display: none;
203 | }
204 |
205 | .bar-color {
206 | height: 20px;
207 | border-right: 3px solid;
208 | box-sizing: content-box;
209 | }
210 |
211 | @each $property in $sliders {
212 | ##{$property} {
213 | .slider-selection, .bar-color {
214 | background-color: unquote(map-get($boxes, #{$property}));
215 | }
216 | .bar-color,
217 | .handle {
218 | border-color: unquote(map-get($boxes, #{$property}));
219 | }
220 | }
221 | }
222 |
223 | @media (min-width: 951px) and (max-width: 1244px) {
224 | .controls {
225 | .sliders label {
226 | display: block;
227 | line-height: 1rem;
228 | &:first-of-type {
229 | margin-top: 8px;
230 | }
231 | }
232 | slider, [slider] {
233 | width: 87%;
234 | }
235 | }
236 | }
237 |
238 | // Toggle
239 | // ---------------------------------------
240 | .toggle {
241 | display: none;
242 | &, &::after, &::before, & *, & *::after, & *::before, & + .toggle-control {
243 | box-sizing: border-box;
244 | &::selection {
245 | background: none;
246 | }
247 | }
248 | + .toggle-control {
249 | outline: 0;
250 | top: 10px;
251 | margin-bottom: 8px;
252 | width: 52px;
253 | position: relative;
254 | cursor: pointer;
255 | user-select: none;
256 | padding: 3px;
257 | @include transition(all 0.3s ease-in-out);
258 | background: $color-bg;
259 | border: $knob-border-width/2 solid $color-dark-lighter;
260 | border-radius: 2em;
261 | &::after, &::before {
262 | position: relative;
263 | display: block;
264 | content:"";
265 | width: $knob-size;
266 | height: $knob-size;
267 | }
268 | &::after {
269 | left: 0;
270 | @include transition(all 0.3s ease-in-out);
271 | background: $color-dark-light;
272 | border-radius: 50%;
273 | }
274 | &::before {
275 | display: none;
276 | }
277 | }
278 | &:checked {
279 | + .toggle-control {
280 | border: $knob-border-width/2 solid $color-dark-lighter;
281 | &::after {
282 | left: 50%;
283 | height: $knob-size;
284 | width: $knob-size;
285 | background: $color-bg;
286 | border: $knob-border-width solid $color-content;
287 | }
288 | }
289 | }
290 | }
291 | .toggle-text {
292 | vertical-align: text-bottom;
293 | margin-left: 5px;
294 | }
295 |
296 |
297 | // Generated Size Change Animation (ng-animate)
298 | // ---------------------------------------
299 | .generated-direction {
300 | display: inline-block;
301 | width: 150px;
302 | }
303 |
304 | .generated-width,
305 | .generated-height {
306 | font-size: 60%;
307 | white-space: nowrap;
308 | font-family: unquote(map-get($bodytype, font-family));
309 | letter-spacing: 1.5px;
310 | text-transform: uppercase;
311 | line-height: 3rem;
312 | @include media($sm) {
313 | line-height: 2rem;
314 | }
315 | .changes {
316 | text-transform: none;
317 | display: inline-block;
318 | line-height: 25px;
319 | padding: 0 5px;
320 | background: #2F353E;
321 | border-radius: 3px;
322 | color: $color-content;
323 | @include transition(color 0.4s ease-in-out, background 0.4s ease-in-out);
324 | &[class*="-add"] {
325 | color: darken($color-content, 45%);
326 | background: $color-content;
327 | }
328 | &.highlight {
329 | &.ng-enter {
330 | background: #2F353E;
331 | color: $color-content;
332 | &.ng-enter-active {
333 | color: darken($color-content, 45%);
334 | background: $color-content;
335 | }
336 | }
337 | &.ng-leave {
338 | color: darken($color-content, 45%);
339 | background: $color-content;
340 | &.ng-leave-active {
341 | background: #2F353E;
342 | color: $color-content;
343 | }
344 | }
345 | }
346 | }
347 | }
348 |
--------------------------------------------------------------------------------
/src/app/styles/partials/_diagram.scss:
--------------------------------------------------------------------------------
1 | $color-margin: #DE6A63;
2 | $color-padding: #C5D936;
3 | $color-content: #63BCF8;
4 | $color-border: #F8CC63;
5 | $color-box-sizing: #8ADFE0;
6 |
7 | $color-bg: #242930;
8 | $color-dark-light: #343434;
9 | $color-dark-lighter: #444;
10 | $color-dark-lightest: #777;
11 | $color-body: #808386;
12 | $color-white: #FFFFFF;
13 |
14 |
15 | $knob-size: 20px;
16 | $knob-border-width: 3px;
17 |
18 | $boxes: (content: $color-content,
19 | padding: $color-padding,
20 | border: $color-border,
21 | margin: $color-margin,
22 | box-sizing: $color-box-sizing,
23 | generated-size: $color-content);
24 |
25 | $sliders: content, padding, border, margin;
26 |
27 | $lg: new-breakpoint(min-width 1245px 7);
28 | $md: new-breakpoint(min-width 950px);
29 | $sm: new-breakpoint(min-width 790px 6);
30 | /*****************************************
31 | * DIAGRAM STYLES
32 | ******************************************/
33 |
34 | #diagram {
35 | margin-left: 5px;
36 | clear: left;
37 | padding-top: $gutter;
38 | }
39 |
40 | .box {
41 | position: relative;
42 | &:hover {
43 | .box-property {
44 | background: $color-white;
45 | }
46 | .box-property-vertical,
47 | .box-property-horizontal {
48 | opacity: 0;
49 | }
50 | }
51 | }
52 |
53 | .box-property {
54 | font-family: unquote(map-get($monospacetype, font-family));
55 | @include transition(width 0.3s linear, height 0.3s linear);
56 | position: absolute;
57 | }
58 |
59 | .box-padding {
60 | @include box-styles($color-padding, dashed, true, 40%);
61 | }
62 | .box-border {
63 | @include box-styles($color-border, solid, true, 50%);
64 | }
65 | .box-margin {
66 | @include box-styles($color-margin, dashed, true, 60%);
67 | /** To Decode this SVG image, paste the css here: www.svgeneration.com/tools/base-64-decoder */
68 |
69 | background-color: #de6a63;
70 | background-image:url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPSc3JyBoZWlnaHQ9JzE0JyB2aWV3Qm94PScwIDAgNSAxMCc+Cgk8cmVjdCB3aWR0aD0nMTEwJScgeD0nLTUlJyB5PSctNSUnIGhlaWdodD0nMTEwJScgZmlsbD0nI2RlNmE2MycvPgoJPGxpbmUgeDE9JzcnIHkxPScxJyB4Mj0nLTInIHkyPScxMCcgc3Ryb2tlPScjZWVhYWE1JyBzdHJva2Utd2lkdGg9JzAuMjknLz4KCTxsaW5lIHgxPSc3JyB5MT0nNicgeDI9Jy0yJyB5Mj0nMTUnIHN0cm9rZT0nI2VlYWFhNScgc3Ryb2tlLXdpZHRoPScwLjI5Jy8+Cgk8bGluZSB4MT0nNycgeTE9Jy00JyB4Mj0nLTInIHkyPSc1JyBzdHJva2U9JyNlZWFhYTUnIHN0cm9rZS13aWR0aD0nMC4yOScvPgo8L3N2Zz4=');
71 |
72 | }
73 |
74 | .box-inner {
75 | @include box-styles($color-content, solid);
76 | text-align: center;
77 | &::before {
78 | color: darken($color-content, 35%);
79 | content: attr(data-width) " x " attr(data-height);
80 | position: absolute;
81 | left: 0;
82 | top: 50%;
83 | margin-top: .5em;
84 | width: 100%;
85 | font-size: .75em;
86 | white-space: nowrap;
87 | }
88 | }
89 |
90 |
91 |
92 | // Box-Property Main Labels
93 | // ---------------------------------------
94 | .property-label {
95 | font-family: unquote(map-get($headingtype, font-family));
96 | text-transform: uppercase;
97 | font-weight: 400;
98 | letter-spacing: 2px;
99 | font-size: 11px;
100 | top: -6px;
101 | @include media($sm) {
102 | top: -12px;
103 | }
104 |
105 | left: 5px;
106 | position: relative;
107 | property-label-padding {
108 | color: darken($color-padding, 15%);
109 | }
110 | property-label-border {
111 | color: darken($color-border, 28%);
112 | }
113 | property-label-margin {
114 | color: darken($color-margin, 20%);
115 | }
116 | property-label-content {
117 | color: darken($color-content, 20%);
118 | float: left;
119 | top: -6px;
120 | @include media($sm) {
121 | top: -8px;
122 | }
123 | }
124 | }
125 |
126 | #padding-v::before {
127 | top: -8px;
128 | }
129 |
130 | %box-property-position {
131 | position: absolute;
132 | top: 0;
133 | left: 0;
134 | z-index: 2000;
135 | &::before, &::after {
136 | position: absolute;
137 | font-size: 0.75em;
138 | text-align: center;
139 | }
140 | }
141 |
142 | %property-vertical {
143 | left: -0.5em;
144 | width: 100%;
145 | }
146 |
147 | %property-horizontal {
148 | margin-top: -0.65em;
149 | width: 2em;
150 | height: 100%;
151 | }
152 |
153 | $properties: zip(vertical horizontal, height width, top left, bottom right, -0.5em -1em);
154 |
155 | @each $direction, $dimension, $offset-before, $offset-after, $amount in $properties {
156 | .box-property-#{$direction} {
157 | @extend %box-property-position;
158 | #{$dimension}: 100%;
159 | &::before {
160 | content:attr(data-#{$offset-before});
161 | @extend %property-#{$direction};
162 | #{$offset-before}: $amount;
163 | }
164 | &::after {
165 | content: attr(data-#{$offset-after});
166 | @extend %property-#{$direction};
167 | #{$offset-after}: $amount;
168 | }
169 | }
170 | }
171 |
172 |
--------------------------------------------------------------------------------
/src/app/styles/partials/_global_layout.scss:
--------------------------------------------------------------------------------
1 |
2 | .browsehappy {
3 | margin: 0.2em 0;
4 | background: #CCC;
5 | color: #000;
6 | padding: 0.2em 0;
7 | }
8 |
9 | // Site-wide base styles.
10 | // Setting root sizes and base styles.
11 | html {
12 | -webkit-text-size-adjust: 100%;
13 | -ms-text-size-adjust: 100%;
14 | @include rootsize;
15 | }
16 |
17 | body {
18 | background-color: $color-bg;
19 | color: $color-body;
20 | overflow-x: hidden;
21 | font-family: unquote(map-get($bodytype, font-family));
22 | font-style: normal;
23 | font-weight: map-get($bodytype, regular);
24 | line-height: 2rem;
25 | @include fontsize(zeta, all);
26 | }
27 |
28 | main {
29 | margin: 20px auto;
30 | padding: 0 20px;
31 | @include outer-container;
32 | }
33 |
34 | $lg: new-breakpoint(min-width 1245px 7);
35 | $md: new-breakpoint(min-width 950px);
36 | $sm: new-breakpoint(min-width 790 6);
37 | // $shorter-sliders: new-breakpoint(min-width 950px);
38 | // $block-labels: new-breakpoint(max-width 950px);
39 | // $md-sm: new-breakpoint(max-width 790px 6);
40 |
41 | .box-model {
42 | @include media($sm) {
43 | @include span-columns(6);
44 | }
45 | @include media($md) {
46 | @include span-columns(7);
47 | }
48 | #content, #generated-size {
49 | @include media($lg) {
50 | @include span-columns(4 of 7);
51 | }
52 | }
53 | #generated-size {
54 | @include media($lg) {
55 | @include span-columns(3 of 7);
56 | @include omega;
57 | }
58 | }
59 | }
60 |
61 | .controls {
62 | @include media($sm) {
63 | @include span-columns(6);
64 | }
65 | @include media($md) {
66 | @include span-columns(5);
67 | }
68 | }
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/src/app/styles/partials/_mixins.scss:
--------------------------------------------------------------------------------
1 | // BOX Style mixins
2 | // --------------------------------------
3 |
4 | @mixin box-property-labels($position) {
5 | .box-property-vertical {
6 | left: $position;
7 | }
8 | .box-property-horizontal {
9 | top: $position;
10 | }
11 | }
12 |
13 | @mixin stagger-labels($position) {
14 | .box-property-vertical {
15 | left: $position;
16 | }
17 | .box-property-horizontal {
18 | top: $position;
19 | }
20 | }
21 |
22 | %hover-opacity {
23 | opacity: 1;
24 | }
25 |
26 | @mixin box-styles($color, $border-style, $position-outer:false, $position:0) {
27 | background: $color;
28 | border: 1px $border-style lighten($color-body, 45%);
29 | text-shadow: 0px 1px 1px transparentize(lighten($color, 20%), 0.3);
30 | span::before,
31 | span::after {
32 | color: darken($color, 40%);
33 | }
34 | &:hover {
35 | background-color: $color !important;
36 | @if position-outer {
37 | .box-property-vertical,
38 | .box-property-horizontal {
39 | @extend %hover-opacity;
40 | opacity: 1;
41 | }
42 | }
43 | }
44 | @if $position-outer {
45 | @include stagger-labels($position);
46 | }
47 | }
48 |
49 |
50 |
51 |
52 | // SCSS mixins
53 | // ---------------------------------------
54 |
55 | // Global variables used in mixins.
56 |
57 | // Number of breakpoints.
58 | $breakpoints-limit: length($breakpoints);
59 |
60 | // List of rootsizes, breakpoints, and max-widths.
61 | $sizes: map-values($rootsizes);
62 | $points: map-values($breakpoints);
63 | $line-widths: map-values($measures);
64 | $max-widths: map-values($maxwidths);
65 |
66 |
67 | // Breakpoints. Either set one to one of the breakpoint variables, or use a custom value for minor breakpoints.
68 | // Defaults to min-width, but both min->max and max-width are available too.
69 | // Parts based on https://gist.github.com/timknight/03e6335b8816aa534cf7
70 | @mixin breakpoint($break: 0, $max: 0) {
71 | // Type of break variable
72 | $value: type-of($break);
73 |
74 | // If it is a string (i.e. a breakpoint variable).
75 | @if $value == string {
76 | // If using 'break-1', 'break-2' etc output the correct breakpoints from map.
77 | @if map-has-key($breakpoints, $break) {
78 | @media screen and (min-width: #{map-get($breakpoints, $break) / 16 * 1em} ) { @content; }
79 | } @else {
80 | @warn "#{$break} is not a set breakpoint variable";
81 | }
82 |
83 | // If it is a number, use this for the breakpoint.
84 | } @else if $value == number {
85 | // If using other numbers output value in ems either for min, min & max or max width breakpoints.
86 | $query: "all" !default;
87 | @if $break != 0 and $max != 0 { $query: "(min-width: #{$break / 16 * 1em}) and (max-width: #{$max / 16 * 1em})"; }
88 | @else if $break != 0 and $max == 0 { $query: "(min-width: #{$break / 16 * 1em})"; }
89 | @else if $break == 0 and $max != 0 { $query: "(max-width: #{$max / 16 * 1em})"; }
90 | @media #{$query} { @content; }
91 |
92 | } @else {
93 | @warn "#{$break} is not valid to use as a breakpoint";
94 | }
95 | }
96 |
97 | // Root font-size in %, outputted in correct breakpoints.
98 | @mixin rootsize {
99 | font-size: nth($sizes, 1) / 16 * 100%;
100 |
101 | // Loop through breakpoints.
102 | @for $i from 2 through $breakpoints-limit {
103 | @media screen and (min-width: nth($points, $i) / 16 * 1em ) {
104 | font-size: nth($sizes, $i) / 16 * 100%;
105 | }
106 | }
107 | }
108 |
109 | // Max-widths for typeset containers, outputted in correct breakpoints.
110 | @mixin maxwidth($breakpoint: 0) {
111 | // Type of chosen variables.
112 | $break-value: type-of($breakpoint);
113 |
114 | // If specifying a breakpoint to use (and breakpoint exists).
115 | @if $break-value == number and $breakpoint <= ($breakpoints-limit - 1) and $breakpoint >= 0 {
116 |
117 | max-width: #{nth($max-widths, ($breakpoint + 1)) / nth($sizes, ($breakpoint + 1))}rem;
118 |
119 | } @else if $breakpoint == all {
120 | max-width: #{nth($max-widths, 1) / nth($sizes, 1)}rem;
121 |
122 | // Loop through breakpoints.
123 | @for $i from 2 through $breakpoints-limit {
124 | @media screen and (min-width: nth($points, $i) / 16 * 1em ) {
125 | max-width: #{nth($max-widths, $i) / nth($sizes, $i)}rem;
126 | }
127 | }
128 | }
129 | }
130 |
131 | // Set the measure for single columns, outputted in correct breakpoints.
132 | @mixin measure($breakpoint: 0) {
133 | // Type of chosen variables.
134 | $break-value: type-of($breakpoint);
135 |
136 | // If specifying a breakpoint to use (and breakpoint exists).
137 | @if $break-value == number and $breakpoint <= ($breakpoints-limit - 1) and $breakpoint >= 0 {
138 |
139 | max-width: #{nth($line-widths, ($breakpoint + 1)) / nth($sizes, ($breakpoint + 1))}rem;
140 |
141 | } @else if $breakpoint == all {
142 | max-width: #{nth($line-widths, 1) / nth($sizes, 1)}rem;
143 |
144 | // Loop through breakpoints.
145 | @for $i from 2 through $breakpoints-limit {
146 | @media screen and (min-width: nth($points, $i) / 16 * 1em ) {
147 | max-width: #{nth($line-widths, $i) / nth($sizes, $i)}rem;
148 | }
149 | }
150 | }
151 | }
152 |
153 | // Calculate percentage width of container to get optimal measure for main text columns.
154 | // Defaults to all breakpoints.
155 | // Note: will not output for base breakpoint as this comes from the 'measure' mixin.
156 | @mixin ideal-measure($breakpoint: 0, $gutter: 0, $main: true, $output: max-width) {
157 | // Type of chosen variables.
158 | $break-value: type-of($breakpoint);
159 |
160 | // If specifying a breakpoint to use (and breakpoint exists and is larger than 0).
161 | @if $break-value == number and $breakpoint <= ($breakpoints-limit - 1) and $breakpoint > 0 {
162 |
163 | @if $gutter == small {
164 | $gutter: map-get($gutterwidths, small) * 2 / 1rem;
165 | } @else if $gutter == medium {
166 | $gutter: map-get($gutterwidths, medium) * 2 / 1rem;
167 | } @else if $gutter == large {
168 | $gutter: map-get($gutterwidths, large) * 2 / 1rem;
169 | } @else {
170 | $gutter: 0;
171 | }
172 |
173 | $rootsize: map-get($rootsizes, rootsize-#{$breakpoint});
174 | $ideal-measure: map-get($measures, measure-#{$breakpoint});
175 | $gutter-size: ($gutter * $rootsize);
176 | $container-width: map-get($maxwidths, width-#{$breakpoint});
177 |
178 | $percentage: percentage(($ideal-measure + $gutter-size) / $container-width);
179 |
180 | @if $percentage < 55 {
181 | $percentage: 55%;
182 | } @else if $percentage > 65 {
183 | $percentage: 65%;
184 | }
185 |
186 | @if $main == false {
187 | $percentage: 100 - $percentage;
188 | }
189 |
190 | #{$output}: $percentage;
191 | }
192 | }
193 |
194 | // Value in scale in $modular-scale?
195 | // Used in following fontsize mixin.
196 | @function in-modular-scale($scale, $key) {
197 | $map: map-get($modular-scale, $scale);
198 | $output: map-has-key($map, $key);
199 | @return $output;
200 | }
201 |
202 | // Font-size in rems. Either set per breakpoint or for all.
203 | // Use values as you would for pixels i.e. 16 or use values from the modular scale.
204 | @mixin fontsize($fontsize, $breakpoint: 0) {
205 | // Type of chosen variables.
206 | $font-value: type-of($fontsize);
207 | $break-value: type-of($breakpoint);
208 |
209 | // Check if value exists in scale.
210 | $in-scale: in-modular-scale(scale-0, $fontsize);
211 |
212 | // If specifying a breakpoint to use (and breakpoint exists).
213 | @if $break-value == number and $breakpoint <= ($breakpoints-limit - 1) and $breakpoint >= 0 {
214 |
215 | // If using a number for fontsize.
216 | @if $font-value == number {
217 | font-size: #{$fontsize / nth($sizes, ($breakpoint + 1))}rem;
218 |
219 | // If using a variable from the scale for fontsize.
220 | } @else if $in-scale == true {
221 | $get-scale: map-get($modular-scale, scale-#{$breakpoint});
222 | $get-size: map-get($get-scale, $fontsize);
223 |
224 | font-size: #{$get-size / nth($sizes, ($breakpoint + 1))}rem;
225 |
226 | } @else {
227 | @warn "#{$fontsize} is not a valid scale variable";
228 | }
229 |
230 | // If want to use value for all breakpoints.
231 | } @else if $breakpoint == all {
232 |
233 | // If using a number for fontsize.
234 | @if $font-value == number {
235 | font-size: #{$fontsize / nth($sizes, 1)}rem;
236 |
237 | // Loop through breakpoints.
238 | @for $i from 2 through $breakpoints-limit {
239 | @media screen and (min-width: nth($points, $i) / 16 * 1em ) {
240 | font-size: #{$fontsize / nth($sizes, $i)}rem;
241 | }
242 | }
243 |
244 | // If using a variable from the scale for fontsize.
245 | } @else if $in-scale == true {
246 | $get-scale: map-get($modular-scale, scale-0);
247 | $get-size: map-get($get-scale, $fontsize);
248 | font-size: #{$get-size / nth($sizes, 1)}rem;
249 |
250 | // Loop through breakpoints.
251 | @for $i from 2 through $breakpoints-limit {
252 | $get-scale: map-get($modular-scale, scale-#{$i - 1});
253 | $get-size: map-get($get-scale, $fontsize);
254 |
255 | @media screen and (min-width: nth($points, $i) / 16 * 1em ) {
256 | font-size: #{$get-size / nth($sizes, $i)}rem;
257 | }
258 | }
259 |
260 | } @else {
261 | @warn "#{$fontsize} is not a valid scale variable";
262 | }
263 |
264 | } @else {
265 | @warn "#{$breakpoint} is not valid to use as a breakpoint";
266 | }
267 | }
268 |
269 | // Advanced baseline magic.
270 | // ! Read the README to help understand what is going on here.
271 | // Parts based on https://gist.github.com/razwan/10662500
272 | @mixin baseline($fontsize, $font, $lineheight: 2, $below: 2, $breakpoint: 0) {
273 | // Type of chosen variables.
274 | $font-value: type-of($fontsize);
275 | $break-value: type-of($breakpoint);
276 |
277 | // Cap height
278 | $cap-height: map-get($font, cap-height);
279 |
280 | // Check if value exists in scale.
281 | $in-scale: in-modular-scale(scale-0, $fontsize);
282 |
283 | // Set the line-height.
284 | line-height: #{$lineheight}rem;
285 |
286 | // If specifying a breakpoint to use (and breakpoint exists).
287 | @if $break-value == number and $breakpoint <= ($breakpoints-limit - 1) and $breakpoint >= 0 {
288 |
289 | // If using a number for fontsize.
290 | @if $font-value == number {
291 | $rootsize: nth($sizes, ($breakpoint + 1));
292 | $baseline-shift: #{($fontsize / 2 * (($lineheight * $rootsize / $fontsize) - $cap-height)) / $rootsize + 0.00001};
293 | $baseline-push: #{$below - (($fontsize / 2 * (($lineheight * $rootsize / $fontsize) - $cap-height)) / $rootsize + 0.00001)};
294 |
295 | margin-bottom: #{$baseline-push}rem;
296 | padding-top: #{$baseline-shift}rem;
297 |
298 | // If using a variable from the scale for fontsize.
299 | } @else if $in-scale == true {
300 | $get-scale: map-get($modular-scale, scale-#{$breakpoint});
301 | $get-size: map-get($get-scale, $fontsize);
302 | $rootsize: nth($sizes, ($breakpoint + 1));
303 |
304 | $baseline-shift: #{($get-size / 2 * (($lineheight * $rootsize / $get-size) - $cap-height)) / $rootsize + 0.00001};
305 | $baseline-push: #{$below - (($get-size / 2 * (($lineheight * $rootsize / $get-size) - $cap-height)) / $rootsize + 0.00001)};
306 |
307 | margin-bottom: #{$baseline-push}rem;
308 | padding-top: #{$baseline-shift}rem;
309 |
310 | } @else {
311 | @warn "#{$fontsize} is not a valid scale variable";
312 | }
313 |
314 | // If want to use value for all breakpoints.
315 | } @else if $breakpoint == all {
316 |
317 | // If using a number for fontsize.
318 | @if $font-value == number {
319 | $rootsize: nth($sizes, 1);
320 | $baseline-shift: #{($fontsize / 2 * (($lineheight * $rootsize / $fontsize) - $cap-height)) / $rootsize + 0.00001};
321 | $baseline-push: #{$below - (($fontsize / 2 * (($lineheight * $rootsize / $fontsize) - $cap-height)) / $rootsize + 0.00001)};
322 |
323 | margin-bottom: #{$baseline-push}rem;
324 | padding-top: #{$baseline-shift}rem;
325 |
326 | // Loop through breakpoints.
327 | @for $i from 2 through $breakpoints-limit {
328 | $rootsize: nth($sizes, $i);
329 | $baseline-shift: #{($fontsize / 2 * (($lineheight * $rootsize / $fontsize) - $cap-height)) / $rootsize + 0.00001};
330 | $baseline-push: #{$below - (($fontsize / 2 * (($lineheight * $rootsize / $fontsize) - $cap-height)) / $rootsize + 0.00001)};
331 |
332 | @media screen and (min-width: nth($points, $i) / 16 * 1em ) {
333 | margin-bottom: #{$baseline-push}rem;
334 | padding-top: #{$baseline-shift}rem;
335 | }
336 | }
337 |
338 | // If using a variable from the scale for fontsize.
339 | } @else if $in-scale == true {
340 | $get-scale: map-get($modular-scale, scale-0);
341 | $get-size: map-get($get-scale, $fontsize);
342 | $rootsize: nth($sizes, 1);
343 |
344 | $baseline-shift: #{($get-size / 2 * (($lineheight * $rootsize / $get-size) - $cap-height)) / $rootsize + 0.00001};
345 | $baseline-push: #{$below - (($get-size / 2 * (($lineheight * $rootsize / $get-size) - $cap-height)) / $rootsize + 0.00001)};
346 |
347 | margin-bottom: #{$baseline-push}rem;
348 | padding-top: #{$baseline-shift}rem;
349 |
350 | // Loop through breakpoints.
351 | @for $i from 2 through $breakpoints-limit {
352 | $get-scale: map-get($modular-scale, scale-#{$i - 1});
353 | $get-size: map-get($get-scale, $fontsize);
354 | $rootsize: nth($sizes, $i);
355 |
356 | $baseline-shift: #{($get-size / 2 * (($lineheight * $rootsize / $get-size) - $cap-height)) / $rootsize + 0.00001};
357 | $baseline-push: #{$below - (($get-size / 2 * (($lineheight * $rootsize / $get-size) - $cap-height)) / $rootsize + 0.00001)};
358 |
359 | @media screen and (min-width: nth($points, $i) / 16 * 1em ) {
360 | margin-bottom: #{$baseline-push}rem;
361 | padding-top: #{$baseline-shift}rem;
362 | }
363 | }
364 |
365 | } @else {
366 | @warn "#{$fontsize} is not a valid scale variable";
367 | }
368 |
369 | } @else {
370 | @warn "#{$breakpoint} is not valid to use as a breakpoint";
371 | }
372 | }
373 |
374 | // Set fontsize and baseline at once. Mix of fontsize and baseline mixin.
375 | @mixin sassline($fontsize, $font, $lineheight: 2, $below: 2, $breakpoint: 0) {
376 | $font-value: type-of($fontsize);
377 | $break-value: type-of($breakpoint);
378 | $cap-height: map-get($font, cap-height);
379 | $in-scale: in-modular-scale(scale-0, $fontsize);
380 |
381 | line-height: #{$lineheight}rem;
382 |
383 | @if $break-value == number and $breakpoint <= ($breakpoints-limit - 1) and $breakpoint >= 0 {
384 |
385 | @if $font-value == number {
386 | $rootsize: nth($sizes, ($breakpoint + 1));
387 | $baseline-shift: #{($fontsize / 2 * (($lineheight * $rootsize / $fontsize) - $cap-height)) / $rootsize + 0.00001};
388 | $baseline-push: #{$below - (($fontsize / 2 * (($lineheight * $rootsize / $fontsize) - $cap-height)) / $rootsize + 0.00001)};
389 | font-size: #{$fontsize / nth($sizes, ($breakpoint + 1))}rem;
390 | margin-bottom: #{$baseline-push}rem;
391 | padding-top: #{$baseline-shift}rem;
392 |
393 | } @else if $in-scale == true {
394 | $get-scale: map-get($modular-scale, scale-#{$breakpoint});
395 | $get-size: map-get($get-scale, $fontsize);
396 | $rootsize: nth($sizes, ($breakpoint + 1));
397 | $baseline-shift: #{($get-size / 2 * (($lineheight * $rootsize / $get-size) - $cap-height)) / $rootsize + 0.00001};
398 | $baseline-push: #{$below - (($get-size / 2 * (($lineheight * $rootsize / $get-size) - $cap-height)) / $rootsize + 0.00001)};
399 | font-size: #{$get-size / nth($sizes, ($breakpoint + 1))}rem;
400 | margin-bottom: #{$baseline-push}rem;
401 | padding-top: #{$baseline-shift}rem;
402 |
403 | } @else {
404 | @warn "#{$fontsize} is not a valid scale variable";
405 | }
406 |
407 | } @else if $breakpoint == all {
408 |
409 | @if $font-value == number {
410 | $rootsize: nth($sizes, 1);
411 | $baseline-shift: #{($fontsize / 2 * (($lineheight * $rootsize / $fontsize) - $cap-height)) / $rootsize + 0.00001};
412 | $baseline-push: #{$below - (($fontsize / 2 * (($lineheight * $rootsize / $fontsize) - $cap-height)) / $rootsize + 0.00001)};
413 | font-size: #{$fontsize / nth($sizes, 1)}rem;
414 | margin-bottom: #{$baseline-push}rem;
415 | padding-top: #{$baseline-shift}rem;
416 |
417 | @for $i from 2 through $breakpoints-limit {
418 | $rootsize: nth($sizes, $i);
419 | $baseline-shift: #{($fontsize / 2 * (($lineheight * $rootsize / $fontsize) - $cap-height)) / $rootsize + 0.00001};
420 | $baseline-push: #{$below - (($fontsize / 2 * (($lineheight * $rootsize / $fontsize) - $cap-height)) / $rootsize + 0.00001)};
421 | @media screen and (min-width: nth($points, $i) / 16 * 1em ) {
422 | font-size: #{$fontsize / nth($sizes, $i)}rem;
423 | margin-bottom: #{$baseline-push}rem;
424 | padding-top: #{$baseline-shift}rem;
425 | }
426 | }
427 |
428 | } @else if $in-scale == true {
429 | $get-scale: map-get($modular-scale, scale-0);
430 | $get-size: map-get($get-scale, $fontsize);
431 | $rootsize: nth($sizes, 1);
432 | $baseline-shift: #{($get-size / 2 * (($lineheight * $rootsize / $get-size) - $cap-height)) / $rootsize + 0.00001};
433 | $baseline-push: #{$below - (($get-size / 2 * (($lineheight * $rootsize / $get-size) - $cap-height)) / $rootsize + 0.00001)};
434 | font-size: #{$get-size / nth($sizes, 1)}rem;
435 | margin-bottom: #{$baseline-push}rem;
436 | padding-top: #{$baseline-shift}rem;
437 |
438 | @for $i from 2 through $breakpoints-limit {
439 | $get-scale: map-get($modular-scale, scale-#{$i - 1});
440 | $get-size: map-get($get-scale, $fontsize);
441 | $rootsize: nth($sizes, $i);
442 | $baseline-shift: #{($get-size / 2 * (($lineheight * $rootsize / $get-size) - $cap-height)) / $rootsize + 0.00001};
443 | $baseline-push: #{$below - (($get-size / 2 * (($lineheight * $rootsize / $get-size) - $cap-height)) / $rootsize + 0.00001)};
444 | @media screen and (min-width: nth($points, $i) / 16 * 1em ) {
445 | font-size: #{$get-size / nth($sizes, $i)}rem;
446 | margin-bottom: #{$baseline-push}rem;
447 | padding-top: #{$baseline-shift}rem;
448 | }
449 | }
450 |
451 | } @else {
452 | @warn "#{$fontsize} is not a valid scale variable";
453 | }
454 |
455 | } @else {
456 | @warn "#{$breakpoint} is not valid to use as a breakpoint";
457 | }
458 | }
459 |
460 | // Clearfix.
461 | @mixin clearfix {
462 | &:before, &:after{
463 | display: table;
464 | content: "";
465 | }
466 | &:after{
467 | clear: both;
468 | }
469 | }
470 |
--------------------------------------------------------------------------------
/src/app/styles/partials/_reset.scss:
--------------------------------------------------------------------------------
1 | // Reset
2 | // ---------------------------------------
3 |
4 | // Reset all the things
5 | * { -moz-box-sizing: border-box; box-sizing: border-box; }
6 | html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; }
7 | article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; }
8 | html, body { height: 100%; }
9 | a img { border: none; }
10 | blockquote { quotes: none; }
11 | blockquote:before, blockquote:after { content: ''; content: none; }
12 | table { border-collapse: collapse; border-spacing: 0; }
13 | caption, th, td { text-align: left; font-weight: normal; vertical-align: middle; }
--------------------------------------------------------------------------------
/src/app/styles/partials/_variables.scss:
--------------------------------------------------------------------------------
1 | // SCSS variables
2 | // ---------------------------------------
3 |
4 | // Note: For the following Sass maps enter values as if they would be px units.
5 |
6 | // Breakpoint sizes from px to ems. Add more values here to add more breakpoints.
7 | // Change names if you prefer, it wont break the mixin as long as they are strings not just numbers.
8 | $breakpoints: (
9 | break-0: 0, // 0px Mobile first
10 | break-1: 640, // 640px ~ Small tablet up
11 | break-2: 800, // 800px ~ Large tablet up
12 | break-3: 1024, // 1024px ~ Desktop up
13 | break-4: 1600 // 1600px ~ Large desktop up
14 | );
15 |
16 | // Root font-sizes for each breakpoint. Set to half desired line-height of body text.
17 | // ! Make sure to have as many sizes as breakpoints above.
18 | $rootsizes: (
19 | rootsize-0: 12, // 24px line-height body text
20 | rootsize-1: 14, // 28px line-height body text
21 | rootsize-2: 15, // 30px line-height body text
22 | rootsize-3: 17, // 34px line-height body text
23 | rootsize-4: 19 // 38px line-height body text
24 | );
25 |
26 | // Set the optimum line-length for your text (based on typeface).
27 | // Aim for 75–100 characters a line when possible, at smaller sizes type size is more important.
28 | // ! Make sure to have as many widths as breakpoints above.
29 | // Note: this was 'maxwidths' in previous versions.
30 | $measures: (
31 | measure-0: 500, // 500px wide
32 | measure-1: 550, // 550px wide
33 | measure-2: 600, // 600px wide
34 | measure-3: 680, // 680px wide
35 | measure-4: 750 // 750px wide
36 | );
37 |
38 | // Set the max-widths for containers (based on design).
39 | // ! Make sure to have as many widths as breakpoints above.
40 | $maxwidths: (
41 | width-0: 500, // 500px wide
42 | width-1: 600, // 600px wide
43 | width-2: 800, // 800px wide
44 | width-3: 1100, // 110px wide
45 | width-4: 1300 // 1300px wide
46 | );
47 |
48 | // Gutter widths
49 | $gutterwidths: (
50 | small: 1rem,
51 | medium: 2rem,
52 | large: 4rem
53 | );
54 |
55 | // Add typefaces here.
56 | // Add weight and style details too.
57 | // ! Set cap height to set to the baseline.
58 |
59 | //TODO: add hosted fonts/include font files
60 |
61 | $bodytype: (
62 | font-family: "'Source Sans Pro','Avenir Next', AvenirNext",
63 | regular: 400,
64 | bold: 700,
65 | italic: italic,
66 | cap-height: 0.62
67 | );
68 |
69 | $headingtype: (
70 | font-family: "'Source Sans Pro','Avenir Next', AvenirNext",
71 | text-transform: uppercase,
72 | regular: 400,
73 | bold: 700,
74 | cap-height: 0.30
75 | );
76 |
77 | $monospacetype: (
78 | font-family: "'Source Code Pro', Menlo, monospace",
79 | regular: 400,
80 | cap-height: 0.68
81 | );
82 |
83 | // Basic Colors
84 | // ---------------------------------------
85 | $color-bg: #242930;
86 | $color-dark-light: #343434;
87 | $color-dark-lighter: #444;
88 | $color-dark-lightest: #777;
89 | $color-body: #808386;
90 | $color-white: #FFFFFF;
91 |
92 |
93 | // Modular scale
94 | // ---------------------------------------
95 |
96 | // Setting responsive modular-scales. Use appropriate scales for viewport sizes.
97 | $modular-scale: (scale-0: (alpha: 28, beta: 25, gamma: 22.4, delta: 20, epsilon: 17.9, zeta: 16, eta: 14.3, theta: 12.8, iota: 11.5), scale-1: (alpha: 30, beta: 26.6, gamma: 24, delta: 21.3, epsilon: 19.2, zeta: 17, eta: 15.3, theta: 13.6, iota: 12.8), scale-2: (alpha: 32, beta: 28.1, gamma: 25.6, delta: 22.5, epsilon: 20.5, zeta: 18, eta: 16.3, theta: 14.4, iota: 13.1), scale-3: (alpha: 40, beta: 35.5, gamma: 30, delta: 26.7, epsilon: 22.5, zeta: 20, eta: 16.9, theta: 15, iota: 12.7), scale-4: (alpha: 50, beta: 43.9, gamma: 35.3, delta: 31.1, epsilon: 25, zeta: 22, eta: 17.6, theta: 15.6, iota: 12.5));
98 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carolineartz/learning-box-model/44333252e3a7cab2cfd76c8255ee59deded18e9a/src/favicon.ico
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | cssBoxModel
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
22 |
23 |
24 |
25 |
26 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/src/tests/main.controller.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Unit: MainCtrl', function () {
4 | beforeEach(module('cssBoxModel'));
5 |
6 | var ctrl, scope;
7 | // inject the $controller and $rootScope services
8 | // in the beforeEach block
9 | beforeEach(inject(function ($controller, $rootScope) {
10 | // Create a new scope that's a child of the $rootScope
11 | scope = $rootScope.$new();
12 | // Create the controller
13 | ctrl = $controller('MainCtrl', {
14 | $scope: scope
15 | });
16 | }));
17 |
18 | it('should create $scope.greeting when calling sayHello',
19 | function () {
20 | expect(scope.greeting).toBeUndefined();
21 | scope.sayHello();
22 | expect(scope.greeting).toEqual("Hello Caroline");
23 | });
24 | })
25 |
--------------------------------------------------------------------------------