Skip to content

Instantly share code, notes, and snippets.

@ScottSmith95
Last active October 22, 2021 13:40
Show Gist options
  • Save ScottSmith95/4417738 to your computer and use it in GitHub Desktop.
Save ScottSmith95/4417738 to your computer and use it in GitHub Desktop.
A responsive web version of iOS Share Sheets. More info: https://ScottHSmith.com/projects/share-sheets/
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
font: normal 300 1em sans-serif;
}
h1 {
text-align: center;
}
ul {
padding: 0;
}
.AllLinks {
margin: 1.5% auto 5% auto;
text-align: center;
height: 1em;
}
.Link {
display: inline;
text-align: center;
line-height: 3.5em;
margin: 0px 0.4%;
cursor: pointer;
}
/* Share Sheets */
.darklayer {
display: none;
position: fixed;
z-index: 9;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0,0,0,0.65);
}
.darklayer.loaded {
display: block;
}
.darklayer.on {
animation: fade-in 0.25s ease-out forwards;
}
.darklayer.off {
animation: fade-out 0.25s ease-out forwards;
}
/* If you use Modernizr.js, the commented code will set nice fallbacks,
instead of the darklayer stuff above.
.js .darklayer {
display: none;
position: fixed;
z-index: 9;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0,0,0,0.5);
}
.js .darklayer.loaded {
display: block;
}
.js .darklayer.on {
animation: fade-in 0.25s ease-out forwards;
}
.js.no-cssanimations .darklayer.on {
display: block;
}
.js .darklayer.off {
animation: fade-out 0.25s ease-out forwards;
}
.js.no-cssanimations .darklayer.off {
display: none;
}*/
.Sheet {
transition: transform 0.25s ease-out;
visibility: hidden;
position: fixed;
z-index: 10;
bottom: 0;
width: 100%;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
font-weight: 400;
user-select: none;
margin: 0 auto;
}
.Sheet.loaded {
visibility: visible;
}
.Sheet.unselected {
transform: translateY(100%);
}
.Sheet.selected {
transform: translateY(0%);
}
.SheetContent {
max-width: 375px;
margin: 0 auto;
}
.itemset {
text-align: left;
background: rgba(248,248,248,0.95);
backdrop-filter: blur(5px);
padding: 1.5em 0 1em;
border-radius: 15px;
margin: 0.6rem auto 0.5rem;
}
.itemset section {
overflow-x: scroll;
-webkit-overflow-scrolling: touch;
padding: 20px 1.5%;
white-space: nowrap;
border-width: 1px;
border-style: solid;
border-image: linear-gradient(to right, #C2C2C6 0%, #D6D6DA 5%, #D6D6DA 95%, #C2C2C6 100%) 100% 0 0 0;
}
.itemset section:first-of-type {
padding-top: 0;
border: none;
}
.itemset section:last-of-type {
padding-bottom: 0;
}
.itemset section:only-child {
padding-top: 0;
padding-bottom: 0;
border: none;
}
.itemset .itemcontainer {
display: inline;
margin: 0;
text-align: center;
}
.itemset li {
display: inline-block;
width: 22.5%;
height: 100%;
margin: 0 auto;
color: #000000;
font-size: 12px;
line-height: 1.3em;
text-align: center;
vertical-align: top;
white-space: normal;
}
.itemset li img {
border-radius: 10px;
}
.itemset li a {
color: inherit;
text-decoration: none;
}
.appicon {
width: auto;
height: 60px;
}
.cancel {
display: block;
width: 100%;
color: #0076FF;
background: rgba(248,248,248,1);
font-size: 20px;
font-weight: 600;
text-align: center;
text-decoration: none;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
padding: 0.8em 0;
border: none;
border-radius: 15px;
margin: 0.5rem auto 0.6rem;
}
.cancel.touched,
.cancel:active {
background: rgba(232, 232, 235, 0.95);
}
/* Landscape */
@media (orientation: landscape) {
.itemset .itemcontainer {
margin: 0 7px;
}
.itemset .itemcontainer:first-child {
margin-left: 0;
}
.itemset .itemcontainer:last-child {
margin-right: 0;
}
}
/* Tablet */
@media (min-width: 45em) {
.SheetContent {
max-width: 450px;
}
.itemset section {
padding-right: 2.5%;
padding-left: 2.5%;
}
.itemset .itemcontainer {
width: 24.5%;
}
.itemset .itemcontainer {
margin: 0 0.25em;
}
.itemset .itemcontainer:first-child {
margin-left: 0;
}
.itemset .itemcontainer:last-child {
margin-right: 0;
}
.itemset li {
width: 20%;
}
.appicon {
height: 75px;
}
}
/* Animations */
@keyframes fade-in {
0% {
visibility: visible;
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes fade-out {
0% {
opacity: 1;
}
100% {
visibility: hidden;
opacity: 0;
}
}
</style>
</head>
<body>
<h1>Select one of the links below to bring up a sheet.</h1>
<ul class="AllLinks">
<li class="Link">
<a class="Twitter">Twitter</a>
</li>
<li class="Link">
<a class="Facebook">Facebook</a>
</li>
</ul>
<!-- Share Sheets -->
<!-- Twitter Share Sheet -->
<div class="Sheet unselected" id="Twitter">
<div class="SheetContent">
<ul class="itemset">
<section class="clients">
<div class="itemcontainer">
<li><a href="twitter://user?screen_name=ScottSmith95">
<img class="appicon" src="https://files.scottshar.es/Share%20Sheets/app-icons/Twitter.png" alt="">
Twitter
</a></li>
</div>
<div class="itemcontainer">
<li><a href="twitterrific:///profile?screen_name=ScottSmith95">
<img class="appicon" src="https://files.scottshar.es/Share%20Sheets/app-icons/Twitterrific.png" alt="">
Twitterrific
</a></li>
</div>
<div class="itemcontainer">
<li><a href="tweetbot:///user_profile/ScottSmith95">
<img class="appicon" src="https://files.scottshar.es/Share%20Sheets/app-icons/Tweetbot.png" alt="">
Tweetbot
</a></li>
</div>
<div class="itemcontainer">
<li><a>
<img class="appicon" src="https://files.scottshar.es/Share%20Sheets/app-icons/Placeholder-Icon.png" alt="">
Placeholder
</a></li>
</div>
<div class="itemcontainer">
<li><a>
<img class="appicon" src="https://files.scottshar.es/Share%20Sheets/app-icons/Placeholder-Icon.png" alt="">
Placeholder
</a></li>
</div>
</section>
<section class="browsers">
<div class="itemcontainer">
<li><a href="https://twitter.com/ScottSmith95">
<img class="appicon" src="https://files.scottshar.es/Share%20Sheets/app-icons/Safari.png" alt="">
Right here
</a></li>
</div>
<div class="itemcontainer">
<li><a href="googlechrome://twitter.com/ScottSmith95">
<img class="appicon" src="https://files.scottshar.es/Share%20Sheets/app-icons/Chrome.png" alt="">
Chrome
</a></li>
</div>
<div class="itemcontainer">
<li><a href="ophttp://twitter.com/ScottSmith95">
<img class="appicon" src="https://files.scottshar.es/Share%20Sheets/app-icons/1Password.png" alt="">
1Password
</a></li>
</div>
</section>
</ul>
<h2 class="cancel">Cancel</h2>
</div>
</div>
<!-- Facebook Share Sheet -->
<div class="Sheet unselected" id="Facebook">
<div class="SheetContent">
<ul class="itemset">
<section>
<div class="itemcontainer">
<li><a href="fb://profile/1618900176">
<img class="appicon" src="https://files.scottshar.es/Share%20Sheets/app-icons/Facebook.png" alt="">
Facebook
</a></li>
</div>
<div class="itemcontainer">
<li><a href="https://facebook.com/ScottSmith95">
<img class="appicon" src="https://files.scottshar.es/Share%20Sheets/app-icons/Safari.png" alt="">
Right here
</a></li>
</div>
<div class="itemcontainer">
<li><a href="googlechrome://facebook.com/ScottSmith95">
<img class="appicon" src="https://files.scottshar.es/Share%20Sheets/app-icons/Chrome.png" alt="">
Chrome
</a></li>
</div>
<div class="itemcontainer">
<li><a href="ophttp://facebook.com/ScottSmith95">
<img class="appicon" src="https://files.scottshar.es/Share%20Sheets/app-icons/1Password.png" alt="">
1Password
</a></li>
</div>
</section>
</ul>
<h2 class="cancel">Cancel</h2>
</div>
</div>
<script>
var sheets = document.querySelectorAll('.Sheet');
var triggers = [document.querySelector('.Twitter'), document.querySelector('.Facebook')];
// Shows sheets after they have loaded.
setTimeout(function(){
// Iterate through the NodeList.
for (var i = 0; i < sheets.length; ++i) {
sheets[i].classList.add('loaded');
}
});
// Handles opening the sheets.
function toggleSheet(sheetID) {
sheet = document.querySelector(sheetID);
if ( sheet.classList.contains('selected') ) {
sheet.classList.remove('selected');
sheet.classList.add('unselected');
sheet.blur();
offDarkLayer();
}
else {
sheet.classList.add('selected');
sheet.classList.remove('unselected');
sheet.focus();
onDarkLayer();
}
}
// Handles adding `<div class="darklayer"></div>` to DOM.
function addDarklayer() {
var element = document.createElement("div");
element.setAttribute('class', 'darklayer off');
document.body.appendChild(element);
}
function onDarkLayer() {
var darkLayer = document.querySelector('.darklayer');
darkLayer.classList.add('loaded');
darkLayer.classList.remove('off');
darkLayer.classList.add('on');
}
function offDarkLayer() {
darkLayer = document.querySelector('.darklayer');
darkLayer.classList.remove('on');
darkLayer.classList.add('off');
}
// Close selected sheet and turn darklayer off.
function offSelectedSheet() {
selectedSheet = document.querySelector('.Sheet.selected');
selectedSheet.blur();
selectedSheet.classList.remove('selected');
selectedSheet.classList.add('unselected');
offDarkLayer();
}
// Add dark layer to DOM.
addDarklayer();
// Link triggers to sheets.
document.querySelector('.Twitter').addEventListener('click', function() {
toggleSheet('#Twitter');
});
document.querySelector('.Facebook').addEventListener('click', function() {
toggleSheet('#Facebook');
});
// Handles all cancel button behviours.
cancelBtns = document.querySelectorAll('.cancel');
for (var i = 0; i < cancelBtns.length; ++i) { // Iterate through the NodeList.
var element = cancelBtns[i];
element.addEventListener('touchstart', function(element) {
element.classList.add('touched');
});
element.addEventListener('touchend', function(element) {
element.classList.remove('touched');
});
element.addEventListener('click', function() {
offSelectedSheet();
});
}
// Handles clicking the darklayer to dismiss sheets.
document.querySelector('.darklayer').addEventListener('click', function() {
offSelectedSheet();
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment