Schrödinger's Website or: “How we built websites of indeterminate design for Adobe Portfolio”

a talk by Jackie Balzer (@jackiebackwards) htps://.wikipedia.org/wiki/File:Schrodinger_cat_in_box.jpg Web Development Life Cycle

Adobe Portfolio

Challenges • Customizations viewed in the editor must be 100% representative of the final product (WYSIWYG)

• Every Thing* must be user-customizable * minus the specifics of the responsive layout

• Responsive styles must look good for infinite- possible customizations Tenets • DRY

• Reusable

• Human writen

• Responsive layout should retain the spirit of the user’s customizations WYSIWYG Challenges: Markup

• The markup you see for your site inside the editor should be the same markup you see on your final published website

WYSIWYG Challenges: CSS

• The styles you see for your site inside the editor should be the result of the same CSS you see on your final published website 1 "header": { 2 "align": "center", 3 "color": "#222", 4 "": { 5 "family": "ftnk", 6 "size": 30, 7 "lineHeight": 30 8 }, 9 "fontStyle": { 10 "bold": "700", 11 "italic": "normal", 12 "underline": null, 13 "": null, 14 "uppercase": "uppercase" 15 }, 16 "padding": { 17 "bottom": 0, 18 "left": 0, 19 "right": 0, 20 "top": 0 21 } 22 } 1 $header: ( 2 align: center, 3 color: #222, 4 font: ( 5 family: ftnk, 6 size: 30, 7 lineHeight: 30 8 ), 9 fontStyle: ( 10 bold: 700, 11 italic: normal, 12 underline: null, 13 strikethrough: null, 14 uppercase: uppercase 15 ), 16 padding: ( 17 bottom: 0, 18 left: 0, 19 right: 0, 20 top: 0 21 ) 22 ); 1 .header { 2 text-align: map-get($header, align); 3 color: map-get($header, color); 4 font-family: map-get($header, font…?); // does not traverse 5 } 1 @function map-me($map, $keys) { 2 3 @each $key in $keys { 4 5 @if map-has-key($map, $key) { 6 $map: map-get($map, $key); 7 } 8 @else { 9 @error 'key "#{$key}" is missing from map'; 10 } 11 12 } // each key in keys 13 14 @return $map; 15 16 } // @function map-me 1 .header { 2 color: map-me($header, color); 3 font-family: map-me($header, font family); 4 font-size: map-me($header, font size); 5 font-style: map-me($header, fontStyle italic); 6 font-weight: map-me($header, fontStyle bold); 7 text-align: map-me($header, align); 8 text-decoration: map-me($header, fontStyle underline) map-me($header, fontStyle strikethrough); 9 line-height: map-me($header, font lineHeight); 10 text-transform: map-me($header, fontStyle uppercase); 11 padding-top: map-me($header, padding top); 12 padding-bottom: map-me($header, padding bottom); 13 padding-left: map-me($header, padding left); 14 padding-right: map-me($header, padding right); 15 } 1 .header { 2 color: #222; 3 font-family: ftnk; 4 font-size: 30px; 5 font-style: normal; 6 font-weight: bold; 7 text-align: center; 8 text-decoration: underline; 9 line-height: 30px; 10 text-transform: uppercase; 11 padding-top: 0; 12 padding-bottom: 0; 13 padding-left: 0; 14 padding-right: 0; 15 }

1 .grid-item:nth-child(var(--number-columns)n+1) { 2 clear: left; 3 } 1 .grid-item:nth-child(#{map-me($grid, per-row)}n+1) { 2 clear: left; 3 } 1 .top-arrow { 2 background: rgba(map-me($arrow, color), map-me($arrow, opacity)); 3 }

Responsive Development

• Many responsive adjustments can be phrased in the form of “if… then”

• Easily modeled using control logic in Sass Responsive Challenges: Layout • Responsive navigation behind a menu 1 // Template default variables 2 $small-breakpoint: 0 540px !global; 3 $medium-breakpoint: 0 768px !global; 1 @include breakpoint($medium-breakpoint) { 2 3 nav { 4 display: none; 5 } 6 7 .hamburger { 8 display: block; 9 } 10 11 }

1 @mixin responsive-nav { 2 3 nav { 4 display: none; 5 } 6 7 .hamburger { 8 display: block; 9 } 10 11 } 1 $theme-features: ( 2 top-header: true, 3 cover-meta-overlay: true, 4 small-responsive-nav-menu: true 5 ); 1 $menu-breakpoint: $medium-breakpoint; 2 @if map-get($theme-features, small-responsive-nav-menu) == true { 3 $menu-breakpoint: $small-breakpoint; 4 } 5 6 @include breakpoint($menu-breakpoint) { 7 @include repsonsive-nav; 8 } Responsive Challenges: Layout • Responsive navigation behind a menu

• Number of columns for grid layouts 1 @include breakpoint($medium-breakpoint) { 2 3 @if map-me($gallery, columns) > 3 { 4 5 // for two- layout 6 7 } 8 9 } // $medium-breakpoint 10 11 @include breakpoint($small-breakpoint) { 12 13 @if map-me($gallery, columns) > 1 { 14 15 // css for 1-column layout 16 17 } 18 19 } // $small-breakpoint Responsive Challenges: Layout • Responsive navigation behind a menu

• Number of columns for grid layouts

• Smaller images should load on smaller screens 1 2 3 4 5 6

1 { 2 "images": { 3 "full": "//path/to/fullsize", 4 "medium": "//path/to/medium-size", 5 "small": "//path/to/small-size" 6 }, 7 "breakpoints": { 8 "full": "min-width: 769px", 9 "medium": "max-width: 768px", 10 "small": "max-width: 540px" 11 } 12 }

Responsive Challenges: Vertical Rhythm

• Spacing scales down on smaller devices

• Font sizes scale accordingly on smaller devices

• Blocks of information ofen rely on relative font sizes (lock up)

Establish rules

• Widths, horizontal margins should always be measured in %

• Font sizes should never go below 14 px

• Bigger numbers should decrease more drastically than smaller numbers Project Date 2016 font-size: 18px line-height: 18px Project Title font-size: 60px Project Title line-height: 64px

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed Project Description diam nonummy nibh euismod tincidunt ut laoreet dolore magna font-size: 22px aliquam erat volutpat. Ut wisi enim ad minim veniam, quis line-height: 28px nostrud exerci tati...

Custom Field Additional Fields font-size: 14px Creative Direction, UX Design, Web Design line-height: 18px 2016 Project Title

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tati...

Custom Field Creative Direction, UX Design, Web Design 2016 Project Title

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tati... Custom Field Creative Direction, UX Design, Web Design

1 @function within-range($item, $min, $max) { 2 $floor: 10; 3 $ceil: 100; 4 @return round(((($max - $min)*($item - $floor))/($ceil - $floor))+$min); 5 } 1 @include breakpoint($medium-breakpoint) { 2 3 .project-title { 4 font-size: within-range(map-me($logo, font-size), 14px, 60px); 5 } 6 7 } 8 9 @include breakpoint($small-breakpoint) { 10 11 .project-title { 12 font-size: within-range(map-me($logo, font-size), 14px, 45px); 13 } 14 15 } THE FUTURE

• Optimize scaling formula

• Optimize output to reduce duplicate values

• Intelligent breakpoint detection

• One CSS generator to rule them all Bread Ned Thanks!

Twiter: @jackiebackwards Email: [email protected]

Adobe Portfolio: myportfolio.com