Merge reset.css into core.css, and add settings page for specifying dark mode preferences

This commit is contained in:
Alex Cabal 2021-01-02 16:53:01 -06:00
parent 27d081b644
commit 11224136d1
9 changed files with 272 additions and 196 deletions

View file

@ -138,6 +138,14 @@ Define domain standardebooks.org
ProxySet connectiontimeout=5 timeout=240 ProxySet connectiontimeout=5 timeout=240
</Proxy> </Proxy>
# In RewriteCond, RewriteRule gets evaluated BEFORE RewriteCond, so $1 refers to the first
# match in RewriteRule
# Rewrite POST /some/url -> POST /some/url/post.php
RewriteCond %{REQUEST_METHOD} ^POST$
RewriteCond %{DOCUMENT_ROOT}/$1/ -d
RewriteCond %{DOCUMENT_ROOT}/$1/post.php -f
RewriteRule ^([^\.]+)$ $1/post.php [L]
# In case of 404, serve the 404 page specified by ErrorDocument, not the default FPM error page. # In case of 404, serve the 404 page specified by ErrorDocument, not the default FPM error page.
# Note that we can't use `ProxyErrorOverride on` because that catches ALL 4xx and 5xx HTTP headers # Note that we can't use `ProxyErrorOverride on` because that catches ALL 4xx and 5xx HTTP headers
# and serves the default Apache page for them. # and serves the default Apache page for them.

View file

@ -137,6 +137,14 @@ Define domain standardebooks.test
ProxySet connectiontimeout=5 timeout=240 ProxySet connectiontimeout=5 timeout=240
</Proxy> </Proxy>
# In RewriteCond, RewriteRule gets evaluated BEFORE RewriteCond, so $1 refers to the first
# match in RewriteRule
# Rewrite POST /some/url -> POST /some/url/post.php
RewriteCond %{REQUEST_METHOD} ^POST$
RewriteCond %{DOCUMENT_ROOT}/$1/ -d
RewriteCond %{DOCUMENT_ROOT}/$1/post.php -f
RewriteRule ^([^\.]+)$ $1/post.php [L]
# In case of 404, serve the 404 page specified by ErrorDocument, not the default FPM error page. # In case of 404, serve the 404 page specified by ErrorDocument, not the default FPM error page.
# Note that we can't use `ProxyErrorOverride on` because that catches ALL 4xx and 5xx HTTP headers # Note that we can't use `ProxyErrorOverride on` because that catches ALL 4xx and 5xx HTTP headers
# and serves the default Apache page for them. # and serves the default Apache page for them.

View file

@ -12,6 +12,9 @@
<li> <li>
<a href="/donate">Donate</a> <a href="/donate">Donate</a>
</li> </li>
<li>
<a href="/settings">Settings</a>
</li>
<li> <li>
<a href="https://github.com/standardebooks">GitHub</a> <a href="https://github.com/standardebooks">GitHub</a>
</li> </li>

View file

@ -16,6 +16,8 @@ if(!isset($manual)){
$manual = false; $manual = false;
} }
$colorScheme = $_COOKIE['color-scheme'] ?? 'auto';
# We hash with crc32 because it's faster than md5 and "good enough" for this simple cache-busting use case # We hash with crc32 because it's faster than md5 and "good enough" for this simple cache-busting use case
header('content-type: application/xhtml+xml'); header('content-type: application/xhtml+xml');
@ -28,8 +30,10 @@ print("\n");
<title><? if($title != ''){ ?><?= Formatter::ToPlainText($title) ?> - <? } ?>Standard Ebooks: Free and liberated ebooks, carefully produced for the true book lover.</title> <title><? if($title != ''){ ?><?= Formatter::ToPlainText($title) ?> - <? } ?>Standard Ebooks: Free and liberated ebooks, carefully produced for the true book lover.</title>
<? if($description != ''){ ?><meta content="<?= Formatter::ToPlainText($description) ?>" name="description"/><? } ?> <? if($description != ''){ ?><meta content="<?= Formatter::ToPlainText($description) ?>" name="description"/><? } ?>
<meta content="width=device-width, initial-scale=1" name="viewport"/> <meta content="width=device-width, initial-scale=1" name="viewport"/>
<link href="/css/reset.css" media="screen" rel="stylesheet" type="text/css"/>
<link href="/css/core.css?version=<?= crc32(file_get_contents(WEB_ROOT . '/css/core.css')) ?>" media="screen" rel="stylesheet" type="text/css"/> <link href="/css/core.css?version=<?= crc32(file_get_contents(WEB_ROOT . '/css/core.css')) ?>" media="screen" rel="stylesheet" type="text/css"/>
<? if($colorScheme == 'auto' || $colorScheme == 'dark'){ ?>
<link href="/css/dark.css?version=<?= crc32(file_get_contents(WEB_ROOT . '/css/dark.css')) ?>" media="screen<? if($colorScheme == 'auto'){ ?> and (prefers-color-scheme: dark)<? } ?>" rel="stylesheet" type="text/css"/>
<? } ?>
<? if($manual){ ?> <? if($manual){ ?>
<link href="/css/manual.css?version=<?= crc32(file_get_contents(WEB_ROOT . '/css/manual.css')) ?>" media="screen" rel="stylesheet" type="text/css"/> <link href="/css/manual.css?version=<?= crc32(file_get_contents(WEB_ROOT . '/css/manual.css')) ?>" media="screen" rel="stylesheet" type="text/css"/>
<? } ?> <? } ?>

View file

@ -95,22 +95,85 @@
--link-highlight: var(--button); --link-highlight: var(--button);
} }
@media(prefers-color-scheme: dark){ /* Start CSS reset */
:root{ /* Dont @import this, to prevent FOUC */
--body-text: var(--dark-body-text); html{
--header: var(--dark-header); margin: 0;
--button: var(--dark-button); padding: 0;
--button-highlight: var(--dark-button-highlight); -ms-text-size-adjust: 100%;
--border: var(--dark-border); -webkit-text-size-adjust: 100%;
--sub-text: var(--dark-sub-text);
--body-bg: var(--dark-body-bg);
--input-hover: var(--dark-input-hover);
--input-border: var(--dark-input-border);
--input-outline: var(--dark-input-outline);
--link-highlight: var(--button-highlight); /* lighter looks better in dark mode */
}
} }
body{
margin: 0;
padding: 0;
}
a{
outline: 0;
}
blockquote{
margin: 0;
quotes: none;
}
p{
margin: 0;
}
ol{
margin: 0;
padding: 0;
}
ul{
margin: 0;
padding: 0;
}
h1{
margin: 0;
}
h2{
margin: 0;
}
h3{
margin: 0;
}
h4{
margin: 0;
}
h5{
margin: 0;
}
h6{
margin: 0;
}
figure{
margin: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
q{
quotes: none;
}
button::-moz-focus-inner{
border: 0;
}
/* End reset */
html{ html{
color: var(--body-text); color: var(--body-text);
font-family: "Crimson Pro", Georgia, serif; font-family: "Crimson Pro", Georgia, serif;
@ -539,6 +602,11 @@ form button{
hyphens: none; hyphens: none;
} }
form button{
line-height: 1;
margin-left: 1rem;
}
.ebooks nav li.highlighted a:focus, .ebooks nav li.highlighted a:focus,
a.button:focus, a.button:focus,
input[type="search"]:focus, input[type="search"]:focus,
@ -1480,6 +1548,10 @@ select[multiple] option:last-child{
margin-bottom: 1rem; /* needed for firefox */ margin-bottom: 1rem; /* needed for firefox */
} }
form[action="/settings"]{
margin: 0 1rem;
}
form[action="/ebooks"] label{ form[action="/ebooks"] label{
max-width: 100%; max-width: 100%;
} }
@ -1932,7 +2004,7 @@ article.ebook section aside.donation p::after{
display: inline; display: inline;
} }
footer ul li:nth-child(3)::after{ footer ul li:nth-child(4)::after{
content: "\A"; /* This is a line break */ content: "\A"; /* This is a line break */
white-space: pre; white-space: pre;
margin: 0; margin: 0;
@ -2051,6 +2123,24 @@ article.ebook section aside.donation p::after{
main.ebooks > ol{ main.ebooks > ol{
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
} }
footer ul li:nth-child(2)::after{
content: "\A"; /* This is a line break */
white-space: pre;
margin: 0;
}
footer ul li:nth-child(4)::after{
content: "\b7";
white-space: normal;
margin: 0 10px;
}
footer ul li:nth-child(5)::after{
content: "\A"; /* This is a line break */
white-space: pre;
margin: 0;
}
} }
@media(max-width: 680px){ @media(max-width: 680px){
@ -2242,10 +2332,16 @@ article.ebook section aside.donation p::after{
text-align: left; text-align: left;
} }
footer ul li:nth-child(5)::after{ form[action="/settings"] button{
content: "\A"; /* This is a line break */ display: block;
white-space: pre; margin-top: 1rem;
margin: 0; margin-left: 0;
}
form[action="/settings"] button,
form[action="/settings"] span,
form[action="/settings"] select{
width: 100%;
} }
} }
@ -2259,16 +2355,6 @@ article.ebook section aside.donation p::after{
.masthead ol li img.contact{ .masthead ol li img.contact{
height: .75rem; height: .75rem;
} }
}
@media(max-width: 380px){
main.front-page h1{
font-size: 2rem;
}
h1,h2,h3,h4,h5,h6,code,.ebook h1 + p{
hyphens: auto;
}
body > footer{ body > footer{
padding-top: 0; padding-top: 0;
@ -2282,6 +2368,16 @@ article.ebook section aside.donation p::after{
footer ul li::after{ footer ul li::after{
display: none; display: none;
} }
}
@media(max-width: 380px){
main.front-page h1{
font-size: 2rem;
}
h1,h2,h3,h4,h5,h6,code,.ebook h1 + p{
hyphens: auto;
}
main.ebooks > ol{ main.ebooks > ol{
grid-template-columns: 1fr; grid-template-columns: 1fr;
@ -2308,7 +2404,6 @@ article.ebook section aside.donation p::after{
grid-row: 6; grid-row: 6;
} }
body > header ul li:nth-child(2n)::after{ body > header ul li:nth-child(2n)::after{
display: none; display: none;
} }
@ -2321,7 +2416,6 @@ article.ebook section aside.donation p::after{
display: none; display: none;
} }
body > header ul li:nth-child(2) ~ li, body > header ul li:nth-child(2) ~ li,
body > header ul li + li{ body > header ul li + li{
margin-top: 1rem; margin-top: 1rem;
@ -2341,73 +2435,3 @@ article.ebook section aside.donation p::after{
text-align: left; text-align: left;
} }
} }
@media(prefers-color-scheme: dark){
main.front-page > section > section figure img{
box-shadow: 3px 3px 1px rgba(0, 0, 0, .5);
}
body > header > a:focus{
/* Since we use invert() to change the color of the SE logo,
we must specify the light outline (which is dark)
so that it inverts to white */
outline: 1px dashed var(--light-input-outline);
}
article.ebook section#read-online a::before,
article.ebook section#download ul li a[class]::before,
article.ebook section#details ul li a[class]::before,
footer p:last-child a::before,
main.front-page > section > section figure.oss img + img,
main.front-page > section > h2::before,
main.front-page > section > h2::after{
filter: invert() grayscale(100%) brightness(120%) drop-shadow(3px 3px 1px rgba(0, 0, 0, .25)); /* grayscale and brightness makes it hit about #eeeeee */
}
.masthead img[src*="portrait.svg"],
.masthead img.contact{
filter: invert();
}
.masthead img[src*="portrait.svg"]{
border-color: var(--border-light);
}
aside.donation,
article.ebook section aside.donation{
background: rgba(0, 0, 0, .25);
}
aside.donation,
article.ebook section aside.donation{
box-shadow: none;
}
select,
input[type="search"]{
box-shadow: 1px 1px 0 rgba(0, 0, 0, .5) inset;
}
input::placeholder{
color: rgba(255, 255, 255, .75);
}
main.ebooks > ol img:hover{
box-shadow: 3px 3px 1px rgba(0, 0, 0, .5);
}
article.ebook #more-ebooks img:hover{
box-shadow: 3px 3px 1px rgba(0, 0, 0, .5);
}
label.select > span + span::after,
label.search::before{
text-shadow: 1px 1px 0 #000;
}
h1,h2,h3,h4,h5,h6{
text-shadow: 2px 2px 0 rgba(0, 0, 0, .75);
}
}

79
www/css/dark.css Normal file
View file

@ -0,0 +1,79 @@
:root{
--body-text: var(--dark-body-text);
--header: var(--dark-header);
--button: var(--dark-button);
--button-highlight: var(--dark-button-highlight);
--border: var(--dark-border);
--sub-text: var(--dark-sub-text);
--body-bg: var(--dark-body-bg);
--input-hover: var(--dark-input-hover);
--input-border: var(--dark-input-border);
--input-outline: var(--dark-input-outline);
--link-highlight: var(--button-highlight); /* lighter looks better in dark mode */
}
main.front-page > section > section figure img{
box-shadow: 3px 3px 1px rgba(0, 0, 0, .5);
}
body > header > a:focus{
/* Since we use invert() to change the color of the SE logo,
we must specify the light outline (which is dark)
so that it inverts to white */
outline: 1px dashed var(--light-input-outline);
}
article.ebook section#read-online a::before,
article.ebook section#download ul li a[class]::before,
article.ebook section#details ul li a[class]::before,
footer p:last-child a::before,
main.front-page > section > section figure.oss img + img,
main.front-page > section > h2::before,
main.front-page > section > h2::after{
filter: invert() grayscale(100%) brightness(120%) drop-shadow(3px 3px 1px rgba(0, 0, 0, .25)); /* grayscale and brightness makes it hit about #eeeeee */
}
.masthead img[src*="portrait.svg"],
.masthead img.contact{
filter: invert();
}
.masthead img[src*="portrait.svg"]{
border-color: var(--border-light);
}
aside.donation,
article.ebook section aside.donation{
background: rgba(0, 0, 0, .25);
}
aside.donation,
article.ebook section aside.donation{
box-shadow: none;
}
select,
input[type="search"]{
box-shadow: 1px 1px 0 rgba(0, 0, 0, .5) inset;
}
input::placeholder{
color: rgba(255, 255, 255, .75);
}
main.ebooks > ol img:hover{
box-shadow: 3px 3px 1px rgba(0, 0, 0, .5);
}
article.ebook #more-ebooks img:hover{
box-shadow: 3px 3px 1px rgba(0, 0, 0, .5);
}
label.select > span + span::after,
label.search::before{
text-shadow: 1px 1px 0 #000;
}
h1,h2,h3,h4,h5,h6{
text-shadow: 2px 2px 0 rgba(0, 0, 0, .75);
}

View file

@ -1,94 +0,0 @@
/* Dont @import this, to prevent FOUC */
html{
margin: 0;
padding: 0;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
body{
margin: 0;
padding: 0;
}
a{
outline: 0;
}
blockquote{
margin: 0;
quotes: none;
}
p{
margin: 0;
}
ol{
margin: 0;
padding: 0;
}
ul{
margin: 0;
padding: 0;
}
h1{
margin: 0;
}
h2{
margin: 0;
}
h3{
margin: 0;
}
h4{
margin: 0;
}
h5{
margin: 0;
}
h6{
margin: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
q{
quotes: none;
}
figure{
margin: 0;
}
button::-moz-focus-inner{
border: 0;
}
/* ie 11 compatibility */
header{
display: block;
}
nav{
display: block;
}
main{
display: block;
}
footer{
display: block;
}
/* end ie 11 compatibility */

23
www/settings/index.php Normal file
View file

@ -0,0 +1,23 @@
<?
require_once('Core.php');
$colorScheme = $_COOKIE['color-scheme'] ?? 'auto';
?><?= Template::Header(['title' => 'Website Settings', 'description' => 'Adjust your settings for viewing the Standard Ebooks website.']) ?>
<main>
<h1>Website Settings</h1>
<form action="/settings" method="post">
<label class="select">
<span>Color scheme</span>
<span>
<select name="color-scheme">
<option value="auto"<? if($colorScheme == 'auto'){ ?> selected="selected"<? } ?>>Automatic</option>
<option value="light"<? if($colorScheme == 'light'){ ?> selected="selected"<? } ?>>Light</option>
<option value="dark"<? if($colorScheme == 'dark'){ ?> selected="selected"<? } ?>>Dark</option>
</select>
</span>
</label>
<button>Apply</button>
</form>
</main>
<?= Template::Footer() ?>

21
www/settings/post.php Normal file
View file

@ -0,0 +1,21 @@
<?
require_once('Core.php');
$colorScheme = $_POST['color-scheme'] ?? 'auto';
if($colorScheme !== 'dark' && $colorScheme !== 'light' && $colorScheme !== 'auto'){
$colorScheme = 'auto';
}
if($colorScheme == 'auto'){
// Delete the cookie; auto is the default
setcookie('color-scheme', null, ['expires' => 0, 'path' => '/', 'secure' => true, 'httponly' => true]);
}
else{
setcookie('color-scheme', $colorScheme, ['expires' => strtotime('+10 years'), 'path' => '/', 'secure' => true, 'httponly' => true]);
}
// HTTP 303, See other
http_response_code(303);
header('Location: /settings');
?>