responsive layout prototypes

This commit is contained in:
Bruno Windels 2019-03-08 12:28:05 +01:00
parent 049e70e312
commit e3d931b966
4 changed files with 643 additions and 0 deletions

View File

@ -0,0 +1,4 @@
CACHE MANIFEST
# v1
/responsive-layout-flex.html
/me.jpg

BIN
prototypes/me.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -0,0 +1,506 @@
<!DOCTYPE html>
<html manifest="manifest.appcache">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no">
<meta name="application-name" content="Talk to Bruno"/>
<meta name="msapplication-navbutton-color" content="red"/>
<style type="text/css">
html {
height: 100%;
display: flex;
min-height: 0;
}
body {
flex: 1;
margin: 0;
display: flex;
flex-direction: column;
font-family: sans-serif;
}
.log {
flex: 0 0 50px;
overflow-y: scroll;
margin: 0;
background: white;
color: black;
word-wrap: anywhere;
display: none;
}
.container {
flex: 1;
display: flex;
min-height: 0;
min-width: 0;
width: 100vw;
}
/* mobile layout */
@media screen and (max-width: 800px) {
.back { display: block !important; }
.room-panel, .room-panel-placeholder { display: none; }
.room-shown .room-panel { display: unset; }
.room-shown .left-panel { display: none; }
.right-shown .timeline-panel { display: none; }
}
.left-panel {
flex: 1;
background: red;
color: white;
overflow-y: auto;
}
.left-panel ul {
list-style: none;
padding: 0;
margin: 0;
}
.left-panel li {
margin: 5px;
padding: 10px;
background: darkred;
display: flex;
align-items: center;
}
.left-panel li > * {
margin-right: 10px;
}
.left-panel div.description {
margin: 0;
flex: 1 1 0;
min-width: 0;
}
.description > * {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.description .last-message {
font-size: 0.8em;
}
.room-panel-placeholder, .room-panel {
flex: 3;
color: white;
background: black;
}
.room-panel {
min-width: 0;
display: none;
}
.room-shown .room-panel {
display: flex;
}
.room-shown .room-panel-placeholder {
display: none;
}
.right-panel {
flex: 1;
background: green;
color: white;
display: none;
}
.timeline-panel {
flex: 3;
min-height: 0;
display: flex;
flex-direction: column;
}
.right-shown .right-panel {
display: block;
}
.room-header {
display: flex;
padding: 10px;
}
.room-header *:last-child {
margin-right: 0 !important;
}
.room-header > * {
margin-right: 10px !important;
}
.room-header button {
width: 40px;
height: 40px;
display: none;
font-size: 1.5em;
padding: 0;
display: block;
background: white;
border: none;
font-weight: bolder;
line-height: 40px;
}
.room-header button.back {
display: none;
}
.room-header .topic {
font-size: 0.8em;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.back::before {
content: "☰";
}
.more::before {
content: "⋮";
}
.room-header {
align-items: center;
}
.room-header .room-description {
flex: 1 1 auto;
min-width: 0;
}
.room-header h2 {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
margin: 0;
}
.timeline-panel ul {
flex: 1;
overflow-y: auto;
list-style: none;
padding: 0;
margin: 0;
}
.timeline-panel li {
background: darkblue;
padding: 10px;
margin: 10px;
}
.composer {
display: flex;
}
.composer input {
display: block;
flex: 1;
font-size: 1.2em;
border: none;
padding: 10px;
}
.avatar {
--avatar-size: 32px;
width: var(--avatar-size);
height: var(--avatar-size);
border-radius: 100px;
overflow: hidden;
flex-shrink: 0;
line-height: var(--avatar-size);
font-size: calc(var(--avatar-size) * 0.6);
text-align: center;
letter-spacing: calc(var(--avatar-size) * -0.05);
background: white;
color: black;
}
.avatar.large {
--avatar-size: 40px;
}
.avatar img {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<ul class="log"></ul>
<div class="container">
<div class="left-panel">
<ul>
<li>
<div class="avatar medium"><img src="me.jpg" alt="Avatar for some room"/></div>
<div class="description">
<div class="name">Room 1</div>
<div class="last-message">Message 12, message 12, message 12</div>
</div>
</li>
<li>
<div class="avatar medium"><img src="me.jpg" alt="Avatar for some room"/></div>
<div class="description">
<div class="name">Room 2</div>
<div class="last-message">Message 12, message 12, message 12</div>
</div>
</li>
<li>
<div class="avatar medium">R3</div>
<div class="description">
<div class="name">Room 3</div>
<div class="last-message">Message 12, message 12, message 12</div>
</div>
</li>
<li>
<div class="avatar medium"><img src="me.jpg" alt="Avatar for some room"/></div>
<div class="description">
<div class="name">Room 4</div>
<div class="last-message">Message 12, message 12, message 12</div>
</div>
</li>
<li>
<div class="avatar medium"><img src="me.jpg" alt="Avatar for some room"/></div>
<div class="description">
<div class="name">Room 5</div>
<div class="last-message">Message 12, message 12, message 12</div>
</div>
</li>
<li>
<div class="avatar medium"><img src="me.jpg" alt="Avatar for some room"/></div>
<div class="description">
<div class="name">Room 6</div>
<div class="last-message">Message 12, message 12, message 12</div>
</div>
</li>
<li>
<div class="avatar medium"><img src="me.jpg" alt="Avatar for some room"/></div>
<div class="description">
<div class="name">Room 7</div>
<div class="last-message">Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</div>
</div>
</li>
<li>
<div class="avatar medium">BW</div>
<div class="description">
<div class="name">Room 8</div>
<div class="last-message">Message 12, message 12, message 12</div>
</div>
</li>
<li>
<div class="avatar medium"><img src="me.jpg" alt="Avatar for some room"/></div>
<div class="description">
<div class="name">Room 9</div>
<div class="last-message">Message 12, message 12, message 12</div>
</div>
</li>
<li>
<div class="avatar medium"><img src="me.jpg" alt="Avatar for some room"/></div>
<div class="description">
<div class="name">Room 10</div>
<div class="last-message">Message 12, message 12, message 12</div>
</div>
</li>
<li>
<div class="avatar medium"><img src="me.jpg" alt="Avatar for some room"/></div>
<div class="description">
<div class="name">Room 11</div>
<div class="last-message">Message 12, message 12, message 12</div>
</div>
</li>
<li>
<div class="avatar medium">🍔</div>
<div class="description">
<div class="name">Room 12</div>
<div class="last-message">Message 12, message 12, message 12</div>
</div>
</li>
<li>
<div class="avatar medium"><img src="me.jpg" alt="Avatar for some room"/></div>
<div class="description">
<div class="name">Room 13</div>
<div class="last-message">Message 12, message 12, message 12</div>
</div>
</li>
<li>
<div class="avatar medium"><img src="me.jpg" alt="Avatar for some room"/></div>
<div class="description">
<div class="name">Room 14</div>
<div class="last-message">Message 12, message 12, message 12</div>
</div>
</li>
</ul>
</div>
<div class="room-panel-placeholder">
<h2>Select a room on the left side</h2>
</div>
<div class="room-panel">
<div class="timeline-panel">
<div class="room-header">
<button class="back"></button>
<div class="avatar large"><img src="me.jpg" alt="Avatar for some room"/></div>
<div class="room-description">
<h2>Talk to Bruno</h2>
<div class="topic">The room to talk to Bruno</div>
</div>
<button class="more"></button>
</div>
<ul>
<li>Message 1, message 1, message 1, message 1, message 1, message 1, message 1, message 1</li>
<li>Message 2, message 2, message 2, message 2, message 2, message 2, message 2, message 2</li>
<li>Message 3, message 3, message 3, message 3, message 3, message 3, message 3, message 3</li>
<li>Message 4, message 4, message 4, message 4, message 4, message 4, message 4, message 4</li>
<li>Message 5, message 5, message 5, message 5, message 5, message 5, message 5, message 5</li>
<li>Message 6, message 6, message 6, message 6, message 6, message 6, message 6, message 6</li>
<li>Message 7, message 7, message 7, message 7, message 7, message 7, message 7, message 7</li>
<li>Message 8, message 8, message 8, message 8, message 8, message 8, message 8, message 8</li>
<li>Message 9, message 9, message 9, message 9, message 9, message 9, message 9, message 9</li>
<li>Message 10, message 10, message 10, message 10, message 10, message 10, message 10, message 10</li>
<li>Message 11, message 11, message 11, message 11, message 11, message 11, message 11, message 11</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
</ul>
<div class="composer"><input type="text" placeholder="Send a message" /></div>
</div>
<div class="right-panel">
<h2>Bruno</h2>
<p>Ban | Kick | Mock</p>
</div>
</div>
</div>
<script type="text/javascript">
const left = document.querySelector(".left-panel");
const room = document.querySelector(".room-panel");
const timeline = document.querySelector(".timeline-panel ul");
const right = document.querySelector(".right-panel");
const back = document.querySelector(".back");
const more = document.querySelector(".more");
const container = document.querySelector(".container");
const logNode = document.querySelector(".log");
const composer = document.querySelector(".composer input");
function fullscreen() {
try {
document.body.webkitRequestFullscreen();
} catch (err) {
log(`could not set fullscreen: ${err.message}`);
}
}
function log(text) {
return;
const li = document.createElement("li");
li.appendChild(document.createTextNode(text));
if (logNode.childElementCount) {
logNode.insertBefore(li, logNode.firstChild);
} else {
logNode.appendChild(li);
}
}
left.addEventListener("click", (e) => {
container.classList.toggle("room-shown");
e.preventDefault();
e.stopPropagation();
});
timeline.addEventListener("click", (e) => {
room.classList.add("right-shown");
e.preventDefault();
e.stopPropagation();
});
right.addEventListener("click", (e) => {
room.classList.remove("right-shown");
e.preventDefault();
e.stopPropagation();
});
back.addEventListener("click", () => {
container.classList.remove("room-shown");
});
more.addEventListener("click", fullscreen);
const isMyPhone = navigator.userAgent.match(/Windows Phone/i);
if (isMyPhone) {
log("on my phone");
} else {
log("not on my phone");
}
window.addEventListener("load", () => {
fullscreen();
setTimeout(() => {
log("hello!");
fullscreen();
}, 100);
});
if (window.applicationCache) {
window.applicationCache.oncached = () => {
log("app is cached now!");
};
window.applicationCache.onupdateready = () => {
log("app has update ready!");
};
}
if (isMyPhone) {
composer.addEventListener("blur", () => {
log(`composer blurred, clearing maxHeight`);
container.style.removeProperty("maxHeight");
container.style.maxHeight = "";
container.style.maxHeight = null;
});
composer.addEventListener("focus", () => {
const h = 640 - 260;
log(`composer focused, setting container height to ${h}`);
container.style.maxHeight = `${h}px`;
});
}
document.scrollingElement.addEventListener("scroll", () => {
log(`window scrolled to ${document.scrollingElement.scrollTop}`);
});
window.addEventListener("resize", () => {
// document.body.style.height = `${window.innerHeight - 100}px`;
// document.scrollingElement.style.background = "red";
// window.scrollTo(0, 0);
log(`window resize ${window.innerHeight}`);
});
</script>
</body>
</html>

View File

@ -0,0 +1,133 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style type="text/css">
body {
height: 100vh;
margin: 0;
display: grid;
}
body { grid-template-columns: 1fr 0 0; }
body.middle-shown { grid-template-columns: 0 1fr 0; }
body.right-shown { grid-template-columns: 0 0 1fr; }
@media(min-width: 800px) {
/*
body without middle-shown is used when having middle-panel-placeholder,
which shouldn't be the panel shown on < 800px)
*/
body, body.middle-shown { grid-template-columns: 2fr 3fr ; }
body.right-shown { grid-template-columns: 0 3fr 2fr; }
}
@media(min-width: 1024px) {
body {
grid-template-columns: 1fr 3fr 0;
}
body.right-shown {
grid-template-columns: 1fr 3fr 1fr;
}
}
.left-panel {
grid-column: 1;
background: red;
color: white;
}
.middle-panel-placeholder, .middle-panel {
color: white;
background: blue;
grid-column: 2;
}
.middle-panel {
display: none;
}
.right-panel {
grid-column: 3;
background: green;
color: white;
display: none;
}
</style>
</head>
<body>
<div class="left-panel">
<ul>
<li>Room 1</li>
<li>Room 2</li>
<li>Room 3</li>
<li>Room 4</li>
<li>Room 5</li>
<li>Room 6</li>
<li>Room 7</li>
<li>Room 8</li>
<li>Room 9</li>
<li>Room 10</li>
<li>Room 11</li>
<li>Room 12</li>
</ul>
</div>
<div class="middle-panel-placeholder">
<h2>Select a room on the left side</h2>
</div>
<div class="middle-panel">
<ul>
<li>Message 1, message 1, message 1, message 1, message 1, message 1, message 1, message 1</li>
<li>Message 2, message 2, message 2, message 2, message 2, message 2, message 2, message 2</li>
<li>Message 3, message 3, message 3, message 3, message 3, message 3, message 3, message 3</li>
<li>Message 4, message 4, message 4, message 4, message 4, message 4, message 4, message 4</li>
<li>Message 5, message 5, message 5, message 5, message 5, message 5, message 5, message 5</li>
<li>Message 6, message 6, message 6, message 6, message 6, message 6, message 6, message 6</li>
<li>Message 7, message 7, message 7, message 7, message 7, message 7, message 7, message 7</li>
<li>Message 8, message 8, message 8, message 8, message 8, message 8, message 8, message 8</li>
<li>Message 9, message 9, message 9, message 9, message 9, message 9, message 9, message 9</li>
<li>Message 10, message 10, message 10, message 10, message 10, message 10, message 10, message 10</li>
<li>Message 11, message 11, message 11, message 11, message 11, message 11, message 11, message 11</li>
<li>Message 12, message 12, message 12, message 12, message 12, message 12, message 12, message 12</li>
</ul>
</div>
<div class="right-panel">
<h2>Bruno</h2>
<p>Ban | Kick | Mock</p>
</div>
<script type="text/javascript">
const left = document.querySelector(".left-panel");
const middle = document.querySelector(".middle-panel");
const middlePlaceholder = document.querySelector(".middle-panel-placeholder");
const right = document.querySelector(".right-panel");
const container = document.body;
left.addEventListener("click", () => {
// middle or right shown
if (container.className) {
container.className = "";
middle.style.display = "";
right.style.display = "";
middlePlaceholder.style.display = "block";
} else {
container.className = "middle-shown";
middle.style.display = "block";
middlePlaceholder.style.display = "none";
right.style.display = "";
}
});
middle.addEventListener("click", () => {
if (container.className === "right-shown") {
container.className = "middle-shown";
right.style.display = "";
} else {
container.className = "right-shown";
right.style.display = "block";
}
});
</script>
</body>
</html>