A Pen by Matthew Daniel Brown on CodePen.
Created
December 12, 2017 23:58
-
-
Save matt-daniel-brown/32db55e75e97de5afa34200ef3a6cab0 to your computer and use it in GitHub Desktop.
Fluid Type Sass - Mixin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<main> | |
<section> | |
<h1>Fluid Typography Sass Mixin</h1> | |
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. | |
Reprehenderit iusto adipisci, cupiditate animi, itaque qui | |
aspernatur vel corrupti labore minima, excepturi ab, fuga rem | |
dolores. Ratione sunt autem iusto aliquid.</p> | |
</section> | |
<section> | |
<h2>Heading 2</h2> | |
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. | |
Reprehenderit iusto adipisci, cupiditate animi, itaque qui | |
aspernatur vel corrupti labore minima, excepturi ab, fuga | |
rem dolores. Ratione sunt autem iusto aliquid.</p> | |
<ul> | |
<li>List Item 1</li> | |
<li>List Item 2</li> | |
<li>List Item 3</li> | |
</ul> | |
<p>Lorem ipsum dolor sit amet, consectetur adipisicing | |
elit. Reprehenderit iusto adipisci, cupiditate animi, | |
itaque qui aspernatur vel corrupti labore minima, excepturi | |
ab, fuga rem dolores. Ratione sunt autem iusto aliquid.</p> | |
<ul class="button-group"> | |
<li><button>Default</button></li> | |
<li><button class="secondary">Secondary</button></li> | |
</ul> | |
</section> | |
</main> | |
<footer> | |
<p>Copyright © 2017.</p> | |
</footer> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* window.onload = function() { | |
// Declare touch variables for older versions of I.E. | |
var pointerDownName = "pointerdown"; | |
var pointerUpName = "pointerup"; | |
var pointerMoveName = "pointermove"; | |
if (window.navigator.msPointerEnabled) { | |
pointerDownName = "MSPointerDown"; | |
pointerUpName = "MSPointerUp"; | |
pointerMoveName = "MSPointerMove"; | |
} | |
// Simple way to check if some form of pointerevents is enabled or not | |
window.PointerEventsSupport = false; | |
if (window.PointerEvent || window.navigator.msPointerEnabled) { | |
window.PointerEventsSupport = true; | |
} | |
// Check if pointer events are supported. | |
if (window.PointerEvent) { | |
// Add Pointer Event Listener | |
swipeFrontElement.addEventListener( | |
"pointerdown", | |
this.handleGestureStart, | |
true | |
); | |
swipeFrontElement.addEventListener( | |
"pointermove", | |
this.handleGestureMove, | |
true | |
); | |
swipeFrontElement.addEventListener("pointerup", this.handleGestureEnd, true); | |
swipeFrontElement.addEventListener( | |
"pointercancel", | |
this.handleGestureEnd, | |
true | |
); | |
} else { | |
// Add Touch Listener | |
swipeFrontElement.addEventListener( | |
"touchstart", | |
this.handleGestureStart, | |
true | |
); | |
swipeFrontElement.addEventListener("touchmove", this.handleGestureMove, true); | |
swipeFrontElement.addEventListener("touchend", this.handleGestureEnd, true); | |
swipeFrontElement.addEventListener( | |
"touchcancel", | |
this.handleGestureEnd, | |
true | |
); | |
// Add Mouse Listener | |
swipeFrontElement.addEventListener( | |
"mousedown", | |
this.handleGestureStart, | |
true | |
); | |
} | |
window.addEventListener("touchstart", func, { passive: true }); | |
if (/iP(hone|ad)/.test(window.navigator.userAgent)) { | |
var elements = document.querySelectorAll("button"); | |
var emptyFunction = function() {}; | |
for (var i = 0; i < elements.length; i++) { | |
elements[i].addEventListener("touchstart", emptyFunction, false); | |
} | |
} | |
}; */ | |
var main = function() { | |
// Shim for requestAnimationFrame from Paul Irishpaul ir | |
// http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/ | |
window.requestAnimFrame = (function(){ | |
'use strict'; | |
return window.requestAnimationFrame || | |
window.webkitRequestAnimationFrame || | |
window.mozRequestAnimationFrame || | |
function( callback ){ | |
window.setTimeout(callback, 1000 / 60); | |
}; | |
})(); | |
/* // [START pointereventsupport] */ | |
var pointerDownName = 'pointerdown'; | |
var pointerUpName = 'pointerup'; | |
var pointerMoveName = 'pointermove'; | |
if(window.navigator.msPointerEnabled) { | |
pointerDownName = 'MSPointerDown'; | |
pointerUpName = 'MSPointerUp'; | |
pointerMoveName = 'MSPointerMove'; | |
} | |
// Simple way to check if some form of pointerevents is enabled or not | |
window.PointerEventsSupport = false; | |
if(window.PointerEvent || window.navigator.msPointerEnabled) { | |
window.PointerEventsSupport = true; | |
} | |
/* // [END pointereventsupport] */ | |
function SwipeRevealItem(element) { | |
'use strict'; | |
// Gloabl state variables | |
var STATE_DEFAULT = 1; | |
var STATE_LEFT_SIDE = 2; | |
var STATE_RIGHT_SIDE = 3; | |
var swipeFrontElement = element.querySelector('.swipe-front'); | |
var rafPending = false; | |
var initialTouchPos = null; | |
var lastTouchPos = null; | |
var currentXPosition = 0; | |
var currentState = STATE_DEFAULT; | |
var handleSize = 10; | |
// Perform client width here as this can be expensive and doens't | |
// change until window.onresize | |
var itemWidth = swipeFrontElement.clientWidth; | |
var slopValue = itemWidth * (1/4); | |
// On resize, change the slop value | |
this.resize = function() { | |
itemWidth = swipeFrontElement.clientWidth; | |
slopValue = itemWidth * (1/4); | |
}; | |
/* // [START handle-start-gesture] */ | |
// Handle the start of gestures | |
this.handleGestureStart = function(evt) { | |
evt.preventDefault(); | |
if(evt.touches && evt.touches.length > 1) { | |
return; | |
} | |
// Add the move and end listeners | |
if (window.PointerEvent) { | |
evt.target.setPointerCapture(evt.pointerId); | |
} else { | |
// Add Mouse Listeners | |
document.addEventListener('mousemove', this.handleGestureMove, true); | |
document.addEventListener('mouseup', this.handleGestureEnd, true); | |
} | |
initialTouchPos = getGesturePointFromEvent(evt); | |
swipeFrontElement.style.transition = 'initial'; | |
}.bind(this); | |
/* // [END handle-start-gesture] */ | |
// Handle move gestures | |
// | |
/* // [START handle-move] */ | |
this.handleGestureMove = function (evt) { | |
evt.preventDefault(); | |
if(!initialTouchPos) { | |
return; | |
} | |
lastTouchPos = getGesturePointFromEvent(evt); | |
if(rafPending) { | |
return; | |
} | |
rafPending = true; | |
window.requestAnimFrame(onAnimFrame); | |
}.bind(this); | |
/* // [END handle-move] */ | |
/* // [START handle-end-gesture] */ | |
// Handle end gestures | |
this.handleGestureEnd = function(evt) { | |
evt.preventDefault(); | |
if(evt.touches && evt.touches.length > 0) { | |
return; | |
} | |
rafPending = false; | |
// Remove Event Listeners | |
if (window.PointerEvent) { | |
evt.target.releasePointerCapture(evt.pointerId); | |
} else { | |
// Remove Mouse Listeners | |
document.removeEventListener('mousemove', this.handleGestureMove, true); | |
document.removeEventListener('mouseup', this.handleGestureEnd, true); | |
} | |
updateSwipeRestPosition(); | |
initialTouchPos = null; | |
}.bind(this); | |
/* // [END handle-end-gesture] */ | |
function updateSwipeRestPosition() { | |
var differenceInX = initialTouchPos.x - lastTouchPos.x; | |
currentXPosition = currentXPosition - differenceInX; | |
// Go to the default state and change | |
var newState = STATE_DEFAULT; | |
// Check if we need to change state to left or right based on slop value | |
if(Math.abs(differenceInX) > slopValue) { | |
if(currentState === STATE_DEFAULT) { | |
if(differenceInX > 0) { | |
newState = STATE_LEFT_SIDE; | |
} else { | |
newState = STATE_RIGHT_SIDE; | |
} | |
} else { | |
if(currentState === STATE_LEFT_SIDE && differenceInX > 0) { | |
newState = STATE_DEFAULT; | |
} else if(currentState === STATE_RIGHT_SIDE && differenceInX < 0) { | |
newState = STATE_DEFAULT; | |
} | |
} | |
} else { | |
newState = currentState; | |
} | |
changeState(newState); | |
swipeFrontElement.style.transition = 'all 150ms ease-out'; | |
} | |
function changeState(newState) { | |
var transformStyle; | |
switch(newState) { | |
case STATE_DEFAULT: | |
currentXPosition = 0; | |
break; | |
case STATE_LEFT_SIDE: | |
currentXPosition = -(itemWidth - handleSize); | |
break; | |
case STATE_RIGHT_SIDE: | |
currentXPosition = itemWidth - handleSize; | |
break; | |
} | |
transformStyle = 'translateX('+currentXPosition+'px)'; | |
swipeFrontElement.style.msTransform = transformStyle; | |
swipeFrontElement.style.MozTransform = transformStyle; | |
swipeFrontElement.style.webkitTransform = transformStyle; | |
swipeFrontElement.style.transform = transformStyle; | |
currentState = newState; | |
} | |
function getGesturePointFromEvent(evt) { | |
var point = {}; | |
if(evt.targetTouches) { | |
point.x = evt.targetTouches[0].clientX; | |
point.y = evt.targetTouches[0].clientY; | |
} else { | |
// Either Mouse event or Pointer Event | |
point.x = evt.clientX; | |
point.y = evt.clientY; | |
} | |
return point; | |
} | |
/* // [START on-anim-frame] */ | |
function onAnimFrame() { | |
if(!rafPending) { | |
return; | |
} | |
var differenceInX = initialTouchPos.x - lastTouchPos.x; | |
var newXTransform = (currentXPosition - differenceInX)+'px'; | |
var transformStyle = 'translateX('+newXTransform+')'; | |
swipeFrontElement.style.webkitTransform = transformStyle; | |
swipeFrontElement.style.MozTransform = transformStyle; | |
swipeFrontElement.style.msTransform = transformStyle; | |
swipeFrontElement.style.transform = transformStyle; | |
rafPending = false; | |
} | |
/* // [END on-anim-frame] */ | |
/* // [START addlisteners] */ | |
// Check if pointer events are supported. | |
if (window.PointerEvent) { | |
// Add Pointer Event Listener | |
swipeFrontElement.addEventListener('pointerdown', this.handleGestureStart, true); | |
swipeFrontElement.addEventListener('pointermove', this.handleGestureMove, true); | |
swipeFrontElement.addEventListener('pointerup', this.handleGestureEnd, true); | |
swipeFrontElement.addEventListener('pointercancel', this.handleGestureEnd, true); | |
} else { | |
// Add Touch Listener | |
swipeFrontElement.addEventListener('touchstart', this.handleGestureStart, true); | |
swipeFrontElement.addEventListener('touchmove', this.handleGestureMove, true); | |
swipeFrontElement.addEventListener('touchend', this.handleGestureEnd, true); | |
swipeFrontElement.addEventListener('touchcancel', this.handleGestureEnd, true); | |
// Add Mouse Listener | |
swipeFrontElement.addEventListener('mousedown', this.handleGestureStart, true); | |
} | |
/* // [END addlisteners] */ | |
} | |
var swipeRevealItems = []; | |
window.onload = function () { | |
'use strict'; | |
var swipeRevealItemElements = document.querySelectorAll('.swipe-element'); | |
for(var i = 0; i < swipeRevealItemElements.length; i++) { | |
swipeRevealItems.push(new SwipeRevealItem(swipeRevealItemElements[i])); | |
} | |
// We do this so :active pseudo classes are applied. | |
window.onload = function() { | |
if(/iP(hone|ad)/.test(window.navigator.userAgent)) { | |
document.body.addEventListener('touchstart', function() {}, false); | |
} | |
}; | |
}; | |
window.onresize = function () { | |
'use strict'; | |
for(var i = 0; i < swipeRevealItems.length; i++) { | |
swipeRevealItems[i].resize(); | |
} | |
}; | |
var registerInteraction = function () { | |
'use strict'; | |
window.sampleCompleted('touch-demo-1.html-SwipeFrontTouch'); | |
}; | |
var swipeFronts = document.querySelectorAll('.swipe-front'); | |
for(var i = 0; i < swipeFronts.length; i++) { | |
swipeFronts[i].addEventListener('touchstart', registerInteraction); | |
} | |
(function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]= | |
function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date; | |
e=o.createElement(i);r=o.getElementsByTagName(i)[0]; | |
e.src='//www.google-analytics.com/analytics.js'; | |
r.parentNode.insertBefore(e,r)}(window,document,'script','ga')); | |
ga('create','UA-52746336-1');ga('send','pageview'); | |
var isCompleted = {}; | |
function sampleCompleted(sampleName){ | |
if (ga && !isCompleted.hasOwnProperty(sampleName)) { | |
ga('send', 'event', 'WebCentralSample', sampleName, 'completed'); | |
isCompleted[sampleName] = true; | |
} | |
} | |
}; | |
window.onload = function() { | |
main; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@import "bourbon@5.*"; | |
$font-family-sans-serif: -apple-system, system-ui, BlinkMacSystemFont, | |
"Segoe UI", "Roboto", "Helvetica Neue", Arial, sans-serif !default; | |
$heading-selectors: (h1, h2, h3, h4, h5); | |
// Requires the calc-interpolation function which can also be used independently | |
@function calc-interpolation($min-screen, $min-value, $max-screen, $max-value) { | |
$a: ($max-value - $min-value) / ($max-screen - $min-screen); | |
$b: $min-value - $a * $min-screen; | |
$sign: "+"; | |
@if ($b < 0) { | |
$sign: "-"; | |
$b: abs($b); | |
} | |
@return calc(#{$a*100}vw #{$sign} #{$b}); | |
} | |
// I'm now recommending this technique: | |
@mixin interpolate($properties, $min-screen, $max-screen, $min-value, $max-value) { | |
& { | |
@each $property in $properties { | |
#{$property}: $min-value; | |
} | |
@media screen and (min-width: $min-screen) { | |
@each $property in $properties { | |
#{$property}: calc-interpolation( | |
$min-screen, | |
$min-value, | |
$max-screen, | |
$max-value | |
); | |
} | |
} | |
@media screen and (min-width: $max-screen) { | |
@each $property in $properties { | |
#{$property}: $max-value; | |
} | |
} | |
} | |
} | |
// Indrek Pass also has a fantastic mixin here: http://sassmeister.com/gist/7f22e44ace49b5124eec | |
* { | |
box-sizing: border-box !important; | |
text-rendering: optimizeLegibility !important; | |
-webkit-font-smoothing: antialiased !important; | |
-moz-osx-font-smoothing: grayscale !important; | |
font-family: $font-family-sans-serif !important; | |
} | |
html { | |
background: #eaeaea; | |
color: #333; | |
@include interpolate(font-size, 320px, 1366px, 14px, 20px); | |
min-width: 300px; | |
padding: 0 !important; | |
margin: 0 !important; | |
touch-action: manipulation; | |
} | |
body { | |
padding: 0 !important; | |
margin: 0 !important; | |
font-weight: 500; | |
line-height: 1.5; | |
} | |
#{$heading-selectors} { | |
@include interpolate((padding-top, padding-bottom), 20rem, 70rem, 0rem, 0.5rem); | |
} | |
main { | |
max-width: 700px; | |
margin: 2rem auto; | |
width: 90%; | |
@media screen and (min-width: 400px) { | |
width: 80%; | |
} | |
} | |
header, | |
footer { | |
padding: 0; | |
width: 100%; | |
margin: 0; | |
height: 6rem; | |
} | |
footer { | |
height: 4rem; | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
align-content: center; | |
justify-content: center; | |
p { | |
color: white; | |
padding: 0 !important; | |
line-height: 1 !important; | |
margin: 0 !important; | |
font-size: 0.75rem; | |
letter-spacing: 1px; | |
color: shade(white, 40%); | |
} | |
} | |
%unstyled-list { | |
list-style: none !important; | |
padding: 0; | |
margin: 0; | |
li { | |
list-style: none !important; | |
padding: 0; | |
margin: 0; | |
} | |
} | |
@mixin horizontal-list { | |
li { | |
display: inline-block; | |
margin-right: 2rem; | |
} | |
} | |
@mixin block-button { | |
width: 100%; | |
margin: 0 !important; | |
} | |
@mixin inline-button { | |
width: 8rem; | |
height: 3rem; | |
display: inline-block; | |
} | |
@mixin button($_baseColor) { | |
appearance: none !important; | |
background: $_baseColor; | |
user-select: none; | |
text-align: center; | |
vertical-align: middle; | |
border-radius: 3px; | |
font-weight: 700; | |
letter-spacing: 1px; | |
cursor: pointer; | |
color: white; | |
line-height: 1 !important; | |
border: 0; | |
width: 100%; | |
display: block; | |
@media screen and (min-width: 450px) { | |
width: 136px; | |
display: inline-block; | |
} | |
height: 48px; | |
font-size: 1rem; | |
transition: all 150ms; | |
vertical-align: center; | |
backface-visibility: hidden; | |
-webkit-tap-highlight-color: 0; | |
-webkit-tap-highlight-color: rgba(#000, 0); | |
-webkit-tap-highlight-color: transparent; | |
background-image: none; | |
-ms-touch-action: none; | |
/* // [START touch-action-example] */ | |
/* Pass all touches to javascript */ | |
touch-action: none; | |
/* // [END touch-action-example] */ | |
&::-moz-focus-inner { | |
border: 0; | |
} | |
&:hover, | |
&:focus { | |
background: shade($_baseColor, 10%); | |
outline: 0; | |
} | |
&:active { | |
background: shade($_baseColor, 20%); | |
outline: 0; | |
transform: translatey(4px); | |
} | |
} | |
button { | |
@include button($_baseColor: shade(#4e7bff, 10%)); | |
&.secondary { | |
@include button($_baseColor: #363b59); | |
} | |
} | |
ul.button-group { | |
@extend %unstyled-list; | |
@include block-button; | |
width: 100%; | |
li { | |
display: block; | |
margin-bottom: 1rem; | |
@media screen and (min-width: 450px) { | |
// width: 136px; | |
display: inline-block; | |
margin-bottom: 0; | |
margin-right: 2rem; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment