jekyll-theme-ethereal 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0538aea84f31c26de9427c683131e533d10a48fcd2ba27f57b71a9a378b77cc4'
4
- data.tar.gz: d524d247a7d8fd95041613f43aa3db2c35862345aabea82845718fc12e778eea
3
+ metadata.gz: 3db3f8ca287a279a5d02be6dd29b109e809cb5b62c344c83543e662545b436c4
4
+ data.tar.gz: 9a2fceee9e20f9f7f57c5cc322143b0e969d1e3c82dbf789d9a687818c28696b
5
5
  SHA512:
6
- metadata.gz: 6dd5bfe81371dd59d541508a218712f6e0aa3d5e99245b1055c56424461bcea706dec112f9f90b1e7e0a2c09f82c754f2142b1e0b7b37915fefeff5c6689684b
7
- data.tar.gz: 96d4ebf5ad61645991ff0557827f2f12bf07cca96af5bce2d96d71311ff122262ef3c6073efdbd6be1ebca6ea4a6e0c9ec6c60c68671a64339156b5b0fc19319
6
+ metadata.gz: 32a8394414ec9f6adc30821131a40902520200440f5e16eb4aa3fda0263f8f881e3e00ce3bb59fa8a788c3b19ee30b13fb72e21b467ce937410f7972a55155a1
7
+ data.tar.gz: cee3582b33ff070e3325ce2fd04b2aea2278cb1a69df9470af33cec87f8a349f82cab0173662b1e4e9b316899a43e6252573b26376739f93102520f200f69007
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  You can preview the theme [here](https://moodule.github.io/jekyll-theme-ethereal)
6
6
 
7
- ![Ethereal Theme](assets/images/screenshot.jpg "Ethereal Theme")
7
+ ![Ethereal Theme](assets/images/screenshot.webp "Ethereal Theme")
8
8
 
9
9
  # Features
10
10
 
@@ -24,6 +24,8 @@ You can preview the theme [here](https://moodule.github.io/jekyll-theme-ethereal
24
24
 
25
25
  > **Light**: svg images, thumbs and lazy loading for raster images, few libraries
26
26
 
27
+ > **Performant**: parallel loading & execution of assets, support lazy-loading, minified assets, compressed critical path
28
+
27
29
  > **Hardened**: form validation, recaptcha, verified libraries
28
30
 
29
31
  # Installation
@@ -80,6 +82,57 @@ The contact form is validated using [google's recaptcha plugin][recaptcha-docume
80
82
  First, you need to [sign your website up] to enable the plugin.
81
83
  Google will provide you with a **client-side integration key**: copy it to `_config.yml` under `recaptcha.sitekey`.
82
84
 
85
+ ## Images
86
+
87
+ ### Lazy-Loading
88
+
89
+ Images downloading & rendering can be defered until they enter the viewport.
90
+ This shortens the loading of the webpage, with no consequence on the displayed content since the images are off-screen.
91
+
92
+ There are 2 possibilities:
93
+ 1) using the scripts bundled with the gem
94
+ 2) depending on the browser
95
+
96
+ Browser support for lazy-loading is varying, so it is recommanded to opt for the first solution.
97
+
98
+ #### Using the gem functionality
99
+
100
+ - add `class="lazy-loading"`
101
+ - fill the attribute `src` with the path to the placeholder file
102
+ - fill the attribute `data-src` with the path to the content file
103
+
104
+ Before:
105
+ ```html
106
+ <img src="{{ 'assets/images/content.jpg' | absolute_url }}" />
107
+ ```
108
+
109
+ After:
110
+ ```html
111
+ <img class="lazy-loading" src="{{ 'assets/images/placeholder.jpg' | absolute_url }}" data-src="{{ 'assets/images/content.jpg' | absolute_url }}" />
112
+ ```
113
+
114
+ #### Using the browser functionality
115
+
116
+ - add `loading="lazy"`
117
+
118
+ Before:
119
+ ```html
120
+ <img src="{{ 'assets/images/content.jpg' | absolute_url }}" />
121
+ ```
122
+
123
+ After:
124
+ ```html
125
+ <img loading="lazy" src="{{ 'assets/images/content.jpg' | absolute_url }}" />
126
+ ```
127
+
128
+ > This functionality is not supported by all the browsers!
129
+
130
+ ### Compression and file formats
131
+
132
+ It is recommanded to use the `webp` format.
133
+
134
+ At a given dimension and compression level (quality) the webp files are at least half the size with a smoother feel.
135
+
83
136
  ## Publication
84
137
 
85
138
  ### On Github Pages
@@ -1,21 +1,25 @@
1
- <form method="post" id="{{ include.form_id | 'contact-form' }}" action="#" onsubmit="{{ include.onsubmit_callback | 'sendContactMessage' }}()" onreset="{{ include.onreset_callback | 'resetContactForm' }}()" >
1
+ <form method="post" id="{{ include.form_id | default: 'contact-form' }}" action="javascript:void(0);" onsubmit="{{ include.onsubmit_callback | default: 'processContactRequest' }}()" onreset="{{ include.onreset_callback | default: 'resetContactForm' }}()" >
2
2
  <div class="fields">
3
3
  <div class="field half">
4
4
  <label for="name">Name</label>
5
- <input type="text" name="{{ include.name_input_id | 'contact-name' }}" id="{{ include.name_input_id | 'contact-name' }}" required minlength="4" maxlength="64" />
5
+ <input type="text" name="{{ include.name_input_id | default: 'contact-name' }}" id="{{ include.name_input_id | default: 'contact-name' }}" placeholder="John Doe" required minlength="4" maxlength="64" onfocusout="{{ include.onfocusout_callback | default: 'toggleSubmitInputElement' }}()" />
6
6
  </div>
7
7
  <div class="field half">
8
8
  <label for="email">Email</label>
9
- <input type="email" name="{{ include.email_input_id | 'contact-email' }}" id="{{ include.email_input_id | 'contact-email' }}" required minlength="8" maxlength="64" />
9
+ <input type="email" name="{{ include.email_input_id | default: 'contact-email' }}" id="{{ include.email_input_id | default: 'contact-email' }}" placeholder="john.doe@example.com" required minlength="8" maxlength="64" onfocusout="{{ include.onfocusout_callback | default: 'toggleSubmitInputElement' }}()" />
10
10
  </div>
11
11
  <div class="field">
12
12
  <label for="message">Message</label>
13
- <textarea name="{{ include.message_input_id | 'contact-message' }}" id="{{ include.message_input_id | 'contact-message' }}" rows="4"vrequired minlength="16" maxlength="256" ></textarea>
13
+ <textarea name="{{ include.message_input_id | default: 'contact-message' }}" id="{{ include.message_input_id | default: 'contact-message' }}" placeholder="Please reach out!" rows="4" required minlength="16" maxlength="256" onfocusout="{{ include.onfocusout_callback | default: 'toggleSubmitInputElement' }}()" ></textarea>
14
14
  </div>
15
15
  </div>
16
16
  <ul class="actions">
17
- <li><div id="{{ include.recaptcha_widget_id | 'recaptcha-checkbox' }}" ></div></li>
18
- <li><input type="submit" id="{{ include.submit_input_id | 'contact-submit-button' }}" value="Send Message" class="button primary fa-envelope" disabled /></li>
19
- <li><input type="reset" id="{{ include.reset_input_id | 'contact-reset-button' }}" value="Reset" class="icon button fa-undo" /></li>
17
+ <li><input type="submit" id="{{ include.submit_input_id | default: 'contact-submit-button' }}" value="Send Message" class="button primary fa-envelope" disabled /></li>
18
+ <li><input type="reset" id="{{ include.reset_input_id | default: 'contact-reset-button' }}" value="Reset" class="icon button fa-undo" /></li>
20
19
  </ul>
20
+ <div id="modal-recaptcha-window" class="modal" tabIndex="-1">
21
+ <div class="inner">
22
+ <div id="{{ include.recaptcha_widget_id | default: 'recaptcha-checkbox' }}" ></div>
23
+ </div>
24
+ </div>
21
25
  </form>
@@ -4,6 +4,7 @@
4
4
  const emailInputElement = document.getElementById("{{ include.email_input_id | default: 'contact-email' }}");
5
5
  const messageInputElement = document.getElementById("{{ include.message_input_id | default: 'contact-message' }}");
6
6
  const submitInputElement = document.getElementById("{{ include.submit_input_id | default: 'contact-submit-button' }}");
7
+ const modalWindowElement = document.getElementById("{{ include.modal_window_id | default: 'modal-recaptcha-window' }}");
7
8
  var recaptchaWidget;
8
9
 
9
10
  const isInputValid = function() {
@@ -11,42 +12,79 @@
11
12
  && emailInputElement.checkValidity()
12
13
  && messageInputElement.checkValidity())
13
14
  };
14
-
15
- const isRecaptchaValid = function() {
16
- var responseToken = grecaptcha.getResponse(recaptchaWidget);
17
- return true;
18
- };
19
15
 
20
16
  const disableSubmitInputElement = function (disabled = true) {
21
17
  submitInputElement.disabled = disabled;
22
18
  }
23
19
 
24
- const {{ include.onreset_callback | 'resetContactForm' }} = function() {
20
+ const {{ include.onfocusout_callback | default: 'toggleSubmitInputElement' }} = function() {
21
+ if (isInputValid()) {
22
+ disableSubmitInputElement(false);
23
+ } else {
24
+ disableSubmitInputElement();
25
+ }
26
+ };
27
+
28
+ const showModalWindow = function() {
29
+ modalWindowElement.classList.add('visible');
30
+ modalWindowElement.classList.add('loaded');
31
+ modalWindowElement.focus();
32
+ }
33
+
34
+ const hideModalWindow = function() {
35
+ modalWindowElement.classList.remove('loaded');
36
+ modalWindowElement.classList.remove('visible');
37
+ contactFormElement.focus();
38
+ }
39
+
40
+ const {{ include.onsubmit_callback | default: 'processContactRequest' }} = function() {
41
+ if (grecaptcha.getResponse(recaptchaWidget).length > 0) {
42
+ sendContactMessage();
43
+ hideModalWindow();
44
+ resetContactForm();
45
+ grecaptcha.reset();
46
+ } else {
47
+ showModalWindow();
48
+ }
49
+ };
50
+
51
+ const {{ include.onreset_callback | default: 'resetContactForm' }} = function() {
25
52
  contactFormElement.reset();
26
53
  disableSubmitInputElement();
27
54
  };
28
55
 
29
- const {{ include.onsubmit_callback | 'sendContactMessage()' }} = function() {
30
- encodeURIComponent(nameInputElement.value);
31
- encodeURIComponent(emailInputElement.value);
32
- encodeURIComponent(messageInputElement.value);
56
+ const sendContactMessage = function() {
57
+ const data = {
58
+ name: encodeURIComponent(nameInputElement.value),
59
+ email: encodeURIComponent(emailInputElement.value),
60
+ message: encodeURIComponent(messageInputElement),
61
+ token: grecaptcha.getResponse(recaptchaWidget)
62
+ };
63
+
64
+ fetch("{{ '/contact' | absolute_url }}", {
65
+ method: 'POST',
66
+ mode: 'same-origin',
67
+ headers: {'Content-Type': 'application/json',},
68
+ body: JSON.stringify(data),
69
+ })
70
+ .then((response) => {
71
+ alert('Message sent!');
72
+ })
73
+ .catch((error) => {
74
+ console.error('Error:', error);
75
+ });
33
76
  };
34
77
 
35
78
  var onloadCallback = function() {
36
- var verifyForm = function(response) {
37
- if (isInputValid() && isRecaptchaValid()) {
38
- disableSubmitInputElement(false);
39
- } else {
40
- disableSubmitInputElement();
41
- }
42
- };
43
- recaptchaWidget = grecaptcha.render('{{ include.recaptcha_widget_id | 'recaptcha-checkbox' }}', {
79
+ recaptchaWidget = grecaptcha.render('{{ include.recaptcha_widget_id | default: 'recaptcha-checkbox' }}', {
44
80
  'sitekey' : '{{ site.recaptcha.sitekey }}',
45
81
  'theme' : 'dark',
46
- 'callback' : verifyForm,
47
- 'expired-callback': disableSubmitInputElement,
48
- 'size' : 'compact'
82
+ 'size' : 'compact',
83
+ 'callback' : processContactRequest
49
84
  });
50
85
  };
86
+
87
+ modalWindowElement.addEventListener('click', hideModalWindow);
88
+ modalWindowElement.addEventListener('keyup', hideModalWindow);
51
89
  </script>
52
- <script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" defer></script>
90
+ <script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" async defer></script>
data/_includes/head.html CHANGED
@@ -5,13 +5,13 @@
5
5
  <meta charset="utf-8" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
7
7
  <link rel="stylesheet" href="{{ 'assets/css/main.css' | absolute_url }}" media="all" />
8
- <link rel="stylesheet" href="{{ 'assets/css/large.css' | absolute_url }}" media="screen and (min-width: 981px) and (max-width:1680px)" />
8
+ <link rel="stylesheet" href="{{ 'assets/css/large.css' | absolute_url }}" media="screen and (min-width: 981px)" />
9
9
  <link rel="stylesheet" href="{{ 'assets/css/medium.css' | absolute_url }}" media="screen and (min-width: 737px) and (max-width:980px)" />
10
10
  <link rel="stylesheet" href="{{ 'assets/css/small.css' | absolute_url }}" media="screen and (max-width:736px)" />
11
11
  <link rel="stylesheet" href="{{ 'assets/css/short.css' | absolute_url }}" media="screen and (min-aspect-ratio:16/7)" />
12
12
  <link rel="preload" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,300i,400i&display=swap" as="style" onload="this.onload=null;this.rel='stylesheet';this.media='all'">
13
13
  <link rel="preload" href="{{ 'assets/css/fontawesome-all.min.css' | absolute_url }}" as="style" onload="this.onload=null;this.rel='stylesheet';this.media='all'">
14
- <link rel="preload" href="{{ 'assets/css/cookieconsent.css' | absolute_url }}" as="style" onload="this.onload=null;this.rel='stylesheet';this.media='all'">
14
+ <link rel="preload" href="{{ 'assets/css/cookieconsent.min.css' | absolute_url }}" as="style" onload="this.onload=null;this.rel='stylesheet';this.media='all'">
15
15
  {%- if include.stylesheets -%}
16
16
  {%- for file in include.stylesheets -%}
17
17
  <link rel="stylesheet" href="{{ file.url | absolute_url }}" />
@@ -24,5 +24,8 @@
24
24
  <link rel="icon" href="{{ site.favicon | absolute_url }}" />
25
25
  {%- endif -%}
26
26
  <noscript><link rel="stylesheet" href="{{ 'assets/css/noscript.css' | absolute_url }}" /></noscript>
27
+ <noscript><link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,300i,400i&display=swap" /></noscript>
28
+ <noscript><link rel="stylesheet" href="{{ 'assets/css/fontawesome-all.min.css' | absolute_url }}" /></noscript>
29
+ <noscript><link rel="stylesheet" href="{{ 'assets/css/cookieconsent.min.css' | absolute_url }}" /></noscript>
27
30
  {% seo %}
28
31
  </head>
@@ -5,19 +5,19 @@
5
5
  {%- assign submit_input_id="contact-submit-button" -%}
6
6
  {%- assign reset_input_id="contact-reset-button" -%}
7
7
  {%- assign recaptcha_widget_id="recaptcha-checkbox" -%}
8
- {%- assign onsubmit_callback="sendContactMessage" -%}
8
+ {%- assign onsubmit_callback="processContactRequest" -%}
9
9
  {%- assign onreset_callback="resetContactForm" -%}
10
-
10
+ {%- assign onfocusout_callback="toggleSubmitInputElement" -%}
11
11
  <div class="intro {{ include.style.header.color | default: 'color4' }}">
12
12
  <h2 class="major">{{ include.header.title | default: 'Contact'}}</h2>
13
13
  <p>{{ include.header.description }}</p>
14
14
  </div>
15
15
  <div class="inner columns divided">
16
16
  <div class="span-3-25">
17
- {% include contact_form.html form_id=form_id name_input_id=name_input_id email_input_id=email_input_id message_input_id=message_input_id submit_input_id=submit_input_id reset_input_id=reset_input_id recaptcha_widget_id=recaptcha_widget_id onsubmit_callback=onsubmit_callback onreset_callback=onreset_callback %}
17
+ {% include contact_form.html form_id=form_id name_input_id=name_input_id email_input_id=email_input_id message_input_id=message_input_id submit_input_id=submit_input_id reset_input_id=reset_input_id recaptcha_widget_id=recaptcha_widget_id onsubmit_callback=onsubmit_callback onreset_callback=onreset_callback onfocusout_callback=onfocusout_callback %}
18
18
  </div>
19
19
  <div class="span-1-5">
20
20
  {% include social.html color=include.style.icons.color %}
21
21
  </div>
22
22
  </div>
23
- {% include contact_script.html form_id=form_id name_input_id=name_input_id email_input_id=email_input_id message_input_id=message_input_id submit_input_id=submit_input_id reset_input_id=reset_input_id recaptcha_widget_id=recaptcha_widget_id onsubmit_callback=onsubmit_callback onreset_callback=onreset_callback %}
23
+ {% include contact_script.html form_id=form_id name_input_id=name_input_id email_input_id=email_input_id message_input_id=message_input_id submit_input_id=submit_input_id reset_input_id=reset_input_id recaptcha_widget_id=recaptcha_widget_id onsubmit_callback=onsubmit_callback onreset_callback=onreset_callback onfocusout_callback=onfocusout_callback %}
@@ -1,5 +1,5 @@
1
- <link rel="stylesheet" href="{{ 'assets/css/mapbox-gl.css' | absolute_url }}" />
2
- <link rel="stylesheet" href="{{ 'assets/css/mapbox-gl.panel.css' | absolute_url }}" />
1
+ <link rel="preload" href="{{ 'assets/css/mapbox-gl.min.css' | absolute_url }}" as="style" onload="this.onload=null;this.rel='stylesheet';this.media='all'">
2
+ <link rel="preload" href="{{ 'assets/css/mapbox-gl.panel.min.css' | absolute_url }}" as="style" onload="this.onload=null;this.rel='stylesheet';this.media='all'">
3
3
  <div class="intro {{ include.style.header.joined }} {{ include.style.header.color }}">
4
4
  <h2 class="major">{{ include.header.title }}</h2>
5
5
  <p>{{ include.header.description }}</p>
@@ -10,7 +10,7 @@ var data_points;
10
10
 
11
11
  function fillMapContainer() {
12
12
  fetch("{{ include.data.file | absolute_url }}")
13
- .then(response => data_points = response.json())
13
+ .then(response => response.json())
14
14
  .then(json => data_points = json);
15
15
 
16
16
  mapboxgl.accessToken = "{{ include.data.token }}";
@@ -2,8 +2,8 @@
2
2
  <script src="{{ 'assets/js/jquery.min.js' | absolute_url }}" type="text/javascript" defer ></script>
3
3
  <script src="{{ 'assets/js/browser.min.js' | absolute_url }}" type="text/javascript" defer ></script>
4
4
  <script src="{{ 'assets/js/breakpoints.min.js' | absolute_url }}" type="text/javascript" defer ></script>
5
- <script src="{{ 'assets/js/lazy-loading.js' | absolute_url }}" type="text/javascript" defer ></script>
6
- <script src="{{ 'assets/js/main.js' | absolute_url }}" type="text/javascript" defer ></script>
5
+ <script src="{{ 'assets/js/lazy-loading.min.js' | absolute_url }}" type="text/javascript" defer ></script>
6
+ <script src="{{ 'assets/js/main.min.js' | absolute_url }}" type="text/javascript" defer ></script>
7
7
  <script src="{{ 'assets/js/cookieconsent.min.js' | absolute_url }}" data-cfasync="false" type="text/javascript" defer ></script>
8
8
  <script src="{{ 'assets/js/cookieconsent.style.min.js' | absolute_url }}" type="text/javascript" defer ></script>
9
9
  {%- if include.scripts -%}
@@ -20,22 +20,22 @@
20
20
 
21
21
  <body class="is-preload">
22
22
 
23
+ {% include language.html %}
24
+
23
25
  <!-- Page Wrapper -->
24
26
  <div id="page-wrapper">
25
27
 
26
28
  <!-- Wrapper -->
27
29
  <div id="wrapper">
28
30
 
29
- {% include language.html %}
30
-
31
31
  {{ content }}
32
32
 
33
- {% include footer.html %}
34
-
35
33
  </div>
36
34
 
37
35
  </div>
38
36
 
37
+ {% include footer.html %}
38
+
39
39
  {% include scripts.html scripts=scripts %}
40
40
 
41
41
  </body>
@@ -63,105 +63,106 @@ $pad-small-lr: _size(pad-small-lr);
63
63
  height: 50%;
64
64
  }
65
65
  }
66
+ }
66
67
 
67
- .modal {
68
- @include vendor('display', 'flex');
69
- @include vendor('align-items', 'center');
70
- @include vendor('justify-content', 'center');
71
- @include vendor('pointer-events', 'none');
72
- @include vendor('user-select', 'none');
68
+
69
+ .modal {
70
+ @include vendor('display', 'flex');
71
+ @include vendor('align-items', 'center');
72
+ @include vendor('justify-content', 'center');
73
+ @include vendor('pointer-events', 'none');
74
+ @include vendor('user-select', 'none');
75
+ @include vendor('transition', (
76
+ 'opacity #{_duration(gallery-lightbox-fadein)} ease',
77
+ 'visibility #{_duration(gallery-lightbox-fadein)}',
78
+ 'z-index #{_duration(gallery-lightbox-fadein)}'
79
+ ));
80
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
81
+ position: fixed;
82
+ top: 0;
83
+ left: 0;
84
+ width: 100%;
85
+ height: 100%;
86
+ background-color: transparentize(_palette(bg), 1 - _misc(gallery-lightbox-opacity));
87
+ opacity: 0;
88
+ outline: 0;
89
+ visibility: none;
90
+ z-index: 0;
91
+
92
+ &:before {
93
+ @include vendor('animation', 'gallery-modal-spinner 1s infinite linear');
94
+ @include vendor('transition', 'opacity #{_duration(gallery-lightbox-fadein) * 0.5} ease');
95
+ @include vendor('transition-delay', '#{_duration(gallery-lightbox-fadein)}');
96
+ content: '';
97
+ display: block;
98
+ position: absolute;
99
+ top: 50%;
100
+ left: 50%;
101
+ width: 4rem;
102
+ height: 4rem;
103
+ margin: -2rem 0 0 -2rem;
104
+ background-image: svg-url('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="96px" height="96px" viewBox="0 0 96 96" zoomAndPan="disable"><style>circle {fill: transparent; stroke: #{_palette(fg-bold)}; stroke-width: 1.5px; }</style><defs><clipPath id="corner"><polygon points="0,0 48,0 48,48 96,48 96,96 0,96" /></clipPath></defs><g clip-path="url(#corner)"><circle cx="48" cy="48" r="32"/></g></svg>');
105
+ background-position: center;
106
+ background-repeat: no-repeat;
107
+ background-size: 4rem;
108
+ opacity: 0;
109
+ }
110
+
111
+ &:after {
112
+ content: '';
113
+ display: block;
114
+ position: absolute;
115
+ top: 0.5rem;
116
+ right: 0.5rem;
117
+ width: 4rem;
118
+ height: 4rem;
119
+ background-image: svg-url('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="64px" height="64px" viewBox="0 0 64 64" zoomAndPan="disable"><style>line {stroke: #{_palette(fg-bold)};stroke-width: 1.5px;}</style><line x1="20" y1="20" x2="44" y2="44" /><line x1="20" y1="44" x2="44" y2="20" /></svg>');
120
+ background-position: center;
121
+ background-repeat: no-repeat;
122
+ background-size: 3rem;
123
+ cursor: pointer;
124
+ }
125
+
126
+ .inner {
127
+ @include vendor('transform', 'translateY(0.75rem)');
73
128
  @include vendor('transition', (
74
- 'opacity #{_duration(gallery-lightbox-fadein)} ease',
75
- 'visibility #{_duration(gallery-lightbox-fadein)}',
76
- 'z-index #{_duration(gallery-lightbox-fadein)}'
129
+ 'opacity #{_duration(gallery-lightbox-fadein) * 0.5} ease',
130
+ 'transform #{_duration(gallery-lightbox-fadein) * 0.5} ease'
77
131
  ));
78
- -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
79
- position: fixed;
80
- top: 0;
81
- left: 0;
82
- width: 100%;
83
- height: 100%;
84
- background-color: transparentize(_palette(bg), 1 - _misc(gallery-lightbox-opacity));
85
132
  opacity: 0;
86
- outline: 0;
87
- visibility: none;
88
- z-index: 0;
89
133
 
90
- &:before {
91
- @include vendor('animation', 'gallery-modal-spinner 1s infinite linear');
92
- @include vendor('transition', 'opacity #{_duration(gallery-lightbox-fadein) * 0.5} ease');
93
- @include vendor('transition-delay', '#{_duration(gallery-lightbox-fadein)}');
94
- content: '';
134
+ img {
95
135
  display: block;
96
- position: absolute;
97
- top: 50%;
98
- left: 50%;
99
- width: 4rem;
100
- height: 4rem;
101
- margin: -2rem 0 0 -2rem;
102
- background-image: svg-url('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="96px" height="96px" viewBox="0 0 96 96" zoomAndPan="disable"><style>circle {fill: transparent; stroke: #{_palette(fg-bold)}; stroke-width: 1.5px; }</style><defs><clipPath id="corner"><polygon points="0,0 48,0 48,48 96,48 96,96 0,96" /></clipPath></defs><g clip-path="url(#corner)"><circle cx="48" cy="48" r="32"/></g></svg>');
103
- background-position: center;
104
- background-repeat: no-repeat;
105
- background-size: 4rem;
106
- opacity: 0;
136
+ max-width: 90vw;
137
+ max-height: 85vh;
138
+ box-shadow: 0 1rem 3rem 0 rgba(0, 0, 0, 0.35);
107
139
  }
140
+ }
108
141
 
109
- &:after {
110
- content: '';
111
- display: block;
112
- position: absolute;
113
- top: 0.5rem;
114
- right: 0.5rem;
115
- width: 4rem;
116
- height: 4rem;
117
- background-image: svg-url('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="64px" height="64px" viewBox="0 0 64 64" zoomAndPan="disable"><style>line {stroke: #{_palette(fg-bold)};stroke-width: 1.5px;}</style><line x1="20" y1="20" x2="44" y2="44" /><line x1="20" y1="44" x2="44" y2="20" /></svg>');
118
- background-position: center;
119
- background-repeat: no-repeat;
120
- background-size: 3rem;
121
- cursor: pointer;
142
+ &.visible {
143
+ @include vendor('pointer-events', 'auto');
144
+ opacity: 1;
145
+ visibility: visible;
146
+ z-index: _misc(z-index-base) + 1000;
147
+
148
+ &:before {
149
+ opacity: 1;
122
150
  }
151
+ }
123
152
 
153
+ &.loaded {
124
154
  .inner {
125
- @include vendor('transform', 'translateY(0.75rem)');
155
+ @include vendor('transform', 'translateY(0)');
126
156
  @include vendor('transition', (
127
- 'opacity #{_duration(gallery-lightbox-fadein) * 0.5} ease',
128
- 'transform #{_duration(gallery-lightbox-fadein) * 0.5} ease'
157
+ 'opacity #{_duration(gallery-lightbox-fadein)} ease',
158
+ 'transform #{_duration(gallery-lightbox-fadein)} ease'
129
159
  ));
130
- opacity: 0;
131
-
132
- img {
133
- display: block;
134
- max-width: 90vw;
135
- max-height: 85vh;
136
- box-shadow: 0 1rem 3rem 0 rgba(0, 0, 0, 0.35);
137
- }
138
- }
139
-
140
- &.visible {
141
- @include vendor('pointer-events', 'auto');
142
160
  opacity: 1;
143
- visibility: visible;
144
- z-index: _misc(z-index-base) + 1000;
145
-
146
- &:before {
147
- opacity: 1;
148
- }
149
161
  }
150
162
 
151
- &.loaded {
152
- .inner {
153
- @include vendor('transform', 'translateY(0)');
154
- @include vendor('transition', (
155
- 'opacity #{_duration(gallery-lightbox-fadein)} ease',
156
- 'transform #{_duration(gallery-lightbox-fadein)} ease'
157
- ));
158
- opacity: 1;
159
- }
160
-
161
- &:before {
162
- @include vendor('transition-delay', '0s');
163
- opacity: 0;
164
- }
163
+ &:before {
164
+ @include vendor('transition-delay', '0s');
165
+ opacity: 0;
165
166
  }
166
167
  }
167
168
  }