jekyll-theme-ethereal 0.5.0 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0538aea84f31c26de9427c683131e533d10a48fcd2ba27f57b71a9a378b77cc4'
4
- data.tar.gz: d524d247a7d8fd95041613f43aa3db2c35862345aabea82845718fc12e778eea
3
+ metadata.gz: 4a78d3f0bfdef625f5d91bf13d6894164fd0c7a06184bdc72b4575193220ab37
4
+ data.tar.gz: 3cdc275827c11c39059917e1b1e56ff97ae31e0e28b553ef004a0ea17b57fd92
5
5
  SHA512:
6
- metadata.gz: 6dd5bfe81371dd59d541508a218712f6e0aa3d5e99245b1055c56424461bcea706dec112f9f90b1e7e0a2c09f82c754f2142b1e0b7b37915fefeff5c6689684b
7
- data.tar.gz: 96d4ebf5ad61645991ff0557827f2f12bf07cca96af5bce2d96d71311ff122262ef3c6073efdbd6be1ebca6ea4a6e0c9ec6c60c68671a64339156b5b0fc19319
6
+ metadata.gz: f5ae046e5831d19b790f8478da55360f00e1ed83e8ad2b8be22a6695747e866513898e91f7a39a12be12378a5229f5c111433c3ab376e96d384953b4804f1089
7
+ data.tar.gz: 38cbc8432a21f74df24706f2c75579355a8a09064f9464582e7a2537f98ea48589679189306a5b7b757cd9c61e2269a5279691a6f1efab8b6a69cc2398e87e9a
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>
@@ -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="stylesheet" href="{{ 'assets/css/mapbox-gl.min.css' | absolute_url }}" media="all">
2
+ <link rel="stylesheet" href="{{ 'assets/css/mapbox-gl.panel.min.css' | absolute_url }}" 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>
@@ -38,6 +38,7 @@ Free for personal and commercial use under the CCA 3.0 license (html5up.net/lice
38
38
  @import 'large/components/gallery';
39
39
  @import 'large/components/panel';
40
40
  @import 'large/components/panel-banner';
41
+ @import 'large/components/panel-map';
41
42
  @import 'large/components/panel-spotlight';
42
43
 
43
44
  // Layout.
File without changes
@@ -4,7 +4,7 @@
4
4
 
5
5
  /// Breakpoints.
6
6
  /// @var {list}
7
- $breakpoints: () !global;
7
+ $breakpoints: null;
8
8
 
9
9
  // Mixins.
10
10
 
@@ -31,6 +31,7 @@ Free for personal and commercial use under the CCA 3.0 license (html5up.net/lice
31
31
  @import 'main/components/gallery';
32
32
  @import 'main/components/panel';
33
33
  @import 'main/components/panel-banner';
34
+ @import 'main/components/panel-map';
34
35
  @import 'main/components/panel-spotlight';
35
36
 
36
37
  // Layout.
@@ -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
  }