main
Raw Download raw file
  1/*
  2 * noVNC base CSS
  3 * Copyright (C) 2019 The noVNC authors
  4 * noVNC is licensed under the MPL 2.0 (see LICENSE.txt)
  5 * This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
  6 */
  7
  8/*
  9 * Z index layers:
 10 *
 11 * 0: Main screen
 12 * 10: Control bar
 13 * 50: Transition blocker
 14 * 60: Connection popups
 15 * 100: Status bar
 16 * ...
 17 * 1000: Javascript crash
 18 * ...
 19 * 10000: Max (used for polyfills)
 20 */
 21
 22/*
 23 * State variables (set on :root):
 24 *
 25 * noVNC_loading: Page is still loading
 26 * noVNC_connecting: Connecting to server
 27 * noVNC_reconnecting: Re-establishing a connection
 28 * noVNC_connected: Connected to server (most common state)
 29 * noVNC_disconnecting: Disconnecting from server
 30 */
 31
 32:root {
 33    font-family: sans-serif;
 34    line-height: 1.6;
 35}
 36
 37body {
 38    margin:0;
 39    padding:0;
 40    /*Background image with light grey curve.*/
 41    background-color:#494949;
 42    background-repeat:no-repeat;
 43    background-position:right bottom;
 44    height:100%;
 45    touch-action: none;
 46}
 47
 48html {
 49    height:100%;
 50}
 51
 52.noVNC_only_touch.noVNC_hidden {
 53    display: none;
 54}
 55
 56.noVNC_disabled {
 57    color: var(--novnc-grey);
 58}
 59
 60/* ----------------------------------------
 61 * Spinner
 62 * ----------------------------------------
 63 */
 64
 65.noVNC_spinner {
 66    position: relative;
 67}
 68.noVNC_spinner, .noVNC_spinner::before, .noVNC_spinner::after {
 69    width: 10px;
 70    height: 10px;
 71    border-radius: 2px;
 72    box-shadow: -60px 10px 0 rgba(255, 255, 255, 0);
 73    animation: noVNC_spinner 1.0s linear infinite;
 74}
 75.noVNC_spinner::before {
 76    content: "";
 77    position: absolute;
 78    left: 0px;
 79    top: 0px;
 80    animation-delay: -0.1s;
 81}
 82.noVNC_spinner::after {
 83    content: "";
 84    position: absolute;
 85    top: 0px;
 86    left: 0px;
 87    animation-delay: 0.1s;
 88}
 89@keyframes noVNC_spinner {
 90    0% { box-shadow: -60px 10px 0 rgba(255, 255, 255, 0); width: 20px; }
 91    25% { box-shadow: 20px 10px 0 rgba(255, 255, 255, 1); width: 10px; }
 92    50% { box-shadow: 60px 10px 0 rgba(255, 255, 255, 0); width: 10px; }
 93}
 94
 95/* ----------------------------------------
 96 * WebKit centering hacks
 97 * ----------------------------------------
 98 */
 99
100.noVNC_center {
101    /*
102     * This is a workaround because webkit misrenders transforms and
103     * uses non-integer coordinates, resulting in blurry content.
104     * Ideally we'd use "top: 50%; transform: translateY(-50%);" on
105     * the objects instead.
106     */
107    display: flex;
108    align-items: center;
109    justify-content: center;
110    position: fixed;
111    top: 0;
112    left: 0;
113    width: 100%;
114    height: 100%;
115    pointer-events: none;
116}
117.noVNC_center > * {
118    pointer-events: auto;
119}
120.noVNC_vcenter {
121    display: flex !important;
122    flex-direction: column;
123    justify-content: center;
124    position: fixed;
125    top: 0;
126    left: 0;
127    height: 100%;
128    margin: 0 !important;
129    padding: 0 !important;
130    pointer-events: none;
131}
132.noVNC_vcenter > * {
133    pointer-events: auto;
134}
135
136/* ----------------------------------------
137 * Layering
138 * ----------------------------------------
139 */
140
141.noVNC_connect_layer {
142    z-index: 60;
143}
144
145/* ----------------------------------------
146 * Fallback error
147 * ----------------------------------------
148 */
149
150#noVNC_fallback_error {
151    z-index: 1000;
152    visibility: hidden;
153    /* Put a dark background in front of everything but the error,
154       and don't let mouse events pass through */
155    background: rgba(0, 0, 0, 0.8);
156    pointer-events: all;
157}
158#noVNC_fallback_error.noVNC_open {
159    visibility: visible;
160}
161
162#noVNC_fallback_error > div {
163    max-width: calc(100vw - 30px - 30px);
164    max-height: calc(100vh - 30px - 30px);
165    overflow: auto;
166
167    padding: 15px;
168
169    transition: 0.5s ease-in-out;
170
171    transform: translateY(-50px);
172    opacity: 0;
173
174    text-align: center;
175    font-weight: bold;
176    color: #fff;
177
178    border-radius: 12px;
179    box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
180    background: rgba(200,55,55,0.8);
181}
182#noVNC_fallback_error.noVNC_open > div {
183    transform: translateY(0);
184    opacity: 1;
185}
186
187#noVNC_fallback_errormsg {
188    font-weight: normal;
189}
190
191#noVNC_fallback_errormsg .noVNC_message {
192    display: inline-block;
193    text-align: left;
194    font-family: monospace;
195    white-space: pre-wrap;
196}
197
198#noVNC_fallback_error .noVNC_location {
199    font-style: italic;
200    font-size: 0.8em;
201    color: rgba(255, 255, 255, 0.8);
202}
203
204#noVNC_fallback_error .noVNC_stack {
205    padding: 10px;
206    margin: 10px;
207    font-size: 0.8em;
208    text-align: left;
209    font-family: monospace;
210    white-space: pre;
211    border: 1px solid rgba(0, 0, 0, 0.5);
212    background: rgba(0, 0, 0, 0.2);
213    overflow: auto;
214}
215
216/* ----------------------------------------
217 * Control bar
218 * ----------------------------------------
219 */
220
221#noVNC_control_bar_anchor {
222    /* The anchor is needed to get z-stacking to work */
223    position: fixed;
224    z-index: 10;
225
226    transition: 0.5s ease-in-out;
227
228    /* Edge misrenders animations wihthout this */
229    transform: translateX(0);
230}
231:root.noVNC_connected #noVNC_control_bar_anchor.noVNC_idle {
232    opacity: 0.8;
233}
234#noVNC_control_bar_anchor.noVNC_right {
235    left: auto;
236    right: 0;
237}
238
239#noVNC_control_bar {
240    position: relative;
241    left: -100%;
242
243    transition: 0.5s ease-in-out;
244
245    background-color: var(--novnc-blue);
246    border-radius: 0 12px 12px 0;
247
248    user-select: none;
249    -webkit-user-select: none;
250    -webkit-touch-callout: none; /* Disable iOS image long-press popup */
251}
252#noVNC_control_bar.noVNC_open {
253    box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
254    left: 0;
255}
256#noVNC_control_bar::before {
257    /* This extra element is to get a proper shadow */
258    content: "";
259    position: absolute;
260    z-index: -1;
261    height: 100%;
262    width: 30px;
263    left: -30px;
264    transition: box-shadow 0.5s ease-in-out;
265}
266#noVNC_control_bar.noVNC_open::before {
267    box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
268}
269.noVNC_right #noVNC_control_bar {
270    left: 100%;
271    border-radius: 12px 0 0 12px;
272}
273.noVNC_right #noVNC_control_bar.noVNC_open {
274    left: 0;
275}
276.noVNC_right #noVNC_control_bar::before {
277    visibility: hidden;
278}
279
280#noVNC_control_bar_handle {
281    position: absolute;
282    left: -15px;
283    top: 0;
284    transform: translateY(35px);
285    width: calc(100% + 30px);
286    height: 50px;
287    z-index: -1;
288    cursor: pointer;
289    border-radius: 6px;
290    background-color: var(--novnc-darkblue);
291    background-image: url("../images/handle_bg.svg");
292    background-repeat: no-repeat;
293    background-position: right;
294    box-shadow: 3px 3px 0px rgba(0, 0, 0, 0.5);
295}
296#noVNC_control_bar_handle:after {
297    content: "";
298    transition: transform 0.5s ease-in-out;
299    background: url("../images/handle.svg");
300    position: absolute;
301    top: 22px; /* (50px-6px)/2 */
302    right: 5px;
303    width: 5px;
304    height: 6px;
305}
306#noVNC_control_bar.noVNC_open #noVNC_control_bar_handle:after {
307    transform: translateX(1px) rotate(180deg);
308}
309:root:not(.noVNC_connected) #noVNC_control_bar_handle {
310    display: none;
311}
312.noVNC_right #noVNC_control_bar_handle {
313    background-position: left;
314}
315.noVNC_right #noVNC_control_bar_handle:after {
316    left: 5px;
317    right: 0;
318    transform: translateX(1px) rotate(180deg);
319}
320.noVNC_right #noVNC_control_bar.noVNC_open #noVNC_control_bar_handle:after {
321    transform: none;
322}
323/* Larger touch area for the handle, used when a touch screen is available */
324#noVNC_control_bar_handle div {
325    position: absolute;
326    right: -35px;
327    top: 0;
328    width: 50px;
329    height: 100%;
330    display: none;
331}
332@media (any-pointer: coarse) {
333    #noVNC_control_bar_handle div {
334        display: initial;
335    }
336}
337.noVNC_right #noVNC_control_bar_handle div {
338    left: -35px;
339    right: auto;
340}
341
342#noVNC_control_bar > .noVNC_scroll {
343    max-height: 100vh; /* Chrome is buggy with 100% */
344    overflow-x: hidden;
345    overflow-y: auto;
346    padding: 0 10px;
347}
348
349#noVNC_control_bar > .noVNC_scroll > * {
350    display: block;
351    margin: 10px auto;
352}
353
354/* Control bar hint */
355#noVNC_hint_anchor {
356    position: fixed;
357    right: -50px;
358    left: auto;
359}
360#noVNC_control_bar_anchor.noVNC_right + #noVNC_hint_anchor {
361    left: -50px;
362    right: auto;
363}
364#noVNC_control_bar_hint {
365    position: relative;
366    transform: scale(0);
367    width: 100px;
368    height: 50%;
369    max-height: 600px;
370
371    visibility: hidden;
372    opacity: 0;
373    transition: 0.2s ease-in-out;
374    background: transparent;
375    box-shadow: 0 0 10px black, inset 0 0 10px 10px var(--novnc-darkblue);
376    border-radius: 12px;
377    transition-delay: 0s;
378}
379#noVNC_control_bar_hint.noVNC_active {
380    visibility: visible;
381    opacity: 1;
382    transition-delay: 0.2s;
383    transform: scale(1);
384}
385#noVNC_control_bar_hint.noVNC_notransition {
386    transition: none !important;
387}
388
389/* Control bar buttons */
390#noVNC_control_bar .noVNC_button {
391    min-width: unset;
392    padding: 4px 4px;
393    vertical-align: middle;
394    border:1px solid rgba(255, 255, 255, 0.2);
395    border-radius: 6px;
396    background-color: transparent;
397}
398#noVNC_control_bar .noVNC_button.noVNC_selected {
399    border-color: rgba(0, 0, 0, 0.8);
400    background-color: rgba(0, 0, 0, 0.5);
401}
402#noVNC_control_bar .noVNC_button.noVNC_hidden {
403    display: none !important;
404}
405
406/* Panels */
407.noVNC_panel {
408    transform: translateX(25px);
409
410    transition: 0.5s ease-in-out;
411
412    box-sizing: border-box; /* so max-width don't have to care about padding */
413    max-width: calc(100vw - 75px - 25px); /* minus left and right margins */
414    max-height: 100vh; /* Chrome is buggy with 100% */
415    overflow-x: hidden;
416    overflow-y: auto;
417
418    visibility: hidden;
419    opacity: 0;
420
421    padding: 15px;
422
423    background: #fff;
424    border-radius: 12px;
425    color: #000;
426    border: 2px solid #E0E0E0;
427    box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
428}
429.noVNC_panel.noVNC_open {
430    visibility: visible;
431    opacity: 1;
432    transform: translateX(75px);
433}
434.noVNC_right .noVNC_vcenter {
435    left: auto;
436    right: 0;
437}
438.noVNC_right .noVNC_panel {
439    transform: translateX(-25px);
440}
441.noVNC_right .noVNC_panel.noVNC_open {
442    transform: translateX(-75px);
443}
444
445.noVNC_panel > * {
446    display: block;
447    margin: 10px auto;
448}
449.noVNC_panel > *:first-child {
450    margin-top: 0 !important;
451}
452.noVNC_panel > *:last-child {
453    margin-bottom: 0 !important;
454}
455
456.noVNC_panel hr {
457    border: none;
458    border-top: 1px solid var(--novnc-lightgrey);
459    width: 100%; /* <hr> inside a flexbox will otherwise be 0px wide */
460}
461
462.noVNC_panel label {
463    display: block;
464    white-space: nowrap;
465    margin: 5px;
466}
467@media (max-width: 540px) {
468    /* Allow wrapping on small screens */
469    .noVNC_panel label {
470        white-space: unset;
471    }
472}
473
474.noVNC_panel li {
475    margin: 5px;
476}
477
478.noVNC_panel .noVNC_heading {
479    background-color: var(--novnc-blue);
480    border-radius: 6px;
481    padding: 5px 8px;
482    /* Compensate for padding in image */
483    padding-right: 11px;
484    display: flex;
485    align-items: center;
486    gap: 6px;
487    color: white;
488    font-size: 20px;
489    font-weight: bold;
490    white-space: nowrap;
491}
492.noVNC_panel .noVNC_heading img {
493    vertical-align: bottom;
494}
495
496.noVNC_panel form {
497    display: flex;
498    flex-direction: column;
499    gap: 12px
500}
501
502.noVNC_panel .button_row {
503    margin-top: 10px;
504    display: flex;
505    gap: 10px;
506    justify-content: space-between;
507}
508.noVNC_panel .button_row *:only-child {
509    margin-left: auto; /* Align single buttons to the right */
510}
511
512/* Expanders */
513.noVNC_expander {
514    cursor: pointer;
515}
516.noVNC_expander::before {
517    content: url("../images/expander.svg");
518    display: inline-block;
519    margin-right: 5px;
520    transition: 0.2s ease-in-out;
521}
522.noVNC_expander.noVNC_open::before {
523    transform: rotateZ(90deg);
524}
525.noVNC_expander ~ * {
526    margin: 5px;
527    margin-left: 10px;
528    padding: 5px;
529    background: rgba(0, 0, 0, 0.04);
530    border-radius: 6px;
531}
532.noVNC_expander:not(.noVNC_open) ~ * {
533    display: none;
534}
535
536/* Control bar content */
537
538#noVNC_control_bar .noVNC_logo {
539    font-size: 13px;
540}
541
542.noVNC_logo + hr {
543    /* Remove all but top border */
544    border: none;
545    border-top: 1px solid rgba(255, 255, 255, 0.2);
546}
547
548:root:not(.noVNC_connected) #noVNC_view_drag_button {
549    display: none;
550}
551
552/* noVNC Touch Device only buttons */
553:root:not(.noVNC_connected) #noVNC_mobile_buttons {
554    display: none;
555}
556@media not all and (any-pointer: coarse) {
557    /* FIXME: The button for the virtual keyboard is the only button in this
558              group of "mobile buttons". It is bad to assume that no touch
559              devices have physical keyboards available. Hopefully we can get
560              a media query for this:
561              https://github.com/w3c/csswg-drafts/issues/3871 */
562    :root.noVNC_connected #noVNC_mobile_buttons {
563        display: none;
564    }
565}
566
567/* Extra manual keys */
568:root:not(.noVNC_connected) #noVNC_toggle_extra_keys_button {
569    display: none;
570}
571
572#noVNC_modifiers {
573    background-color: var(--novnc-darkgrey);
574    border: none;
575    padding: 10px;
576}
577
578/* Shutdown/Reboot */
579:root:not(.noVNC_connected) #noVNC_power_button {
580    display: none;
581}
582#noVNC_power {
583}
584#noVNC_power_buttons {
585    display: none;
586}
587
588#noVNC_power input[type=button] {
589    width: 100%;
590}
591
592/* Clipboard */
593:root:not(.noVNC_connected) #noVNC_clipboard_button {
594    display: none;
595}
596#noVNC_clipboard_text {
597    width: 360px;
598    min-width: 150px;
599    height: 160px;
600    min-height: 70px;
601
602    box-sizing: border-box;
603    max-width: 100%;
604    /* minus approximate height of title, height of subtitle, and margin */
605    max-height: calc(100vh - 10em - 25px);
606}
607
608/* Settings */
609#noVNC_settings {
610}
611#noVNC_settings ul {
612    list-style: none;
613    padding: 0px;
614}
615#noVNC_settings button,
616#noVNC_settings select,
617#noVNC_settings textarea,
618#noVNC_settings input:not([type=checkbox]):not([type=radio]) {
619    margin-left: 6px;
620    /* Prevent inputs in settings from being too wide */
621    max-width: calc(100% - 6px - var(--input-xpadding) * 2);
622}
623
624#noVNC_setting_port {
625    width: 80px;
626}
627#noVNC_setting_path {
628    width: 100px;
629}
630
631/* Version */
632
633.noVNC_version_wrapper {
634    font-size: small;
635}
636
637.noVNC_version {
638    margin-left: 1rem;
639}
640
641/* Connection controls */
642:root:not(.noVNC_connected) #noVNC_disconnect_button {
643    display: none;
644}
645
646/* ----------------------------------------
647 * Status dialog
648 * ----------------------------------------
649 */
650
651#noVNC_status {
652    position: fixed;
653    top: 0;
654    left: 0;
655    width: 100%;
656    z-index: 100;
657    transform: translateY(-100%);
658
659    cursor: pointer;
660
661    transition: 0.5s ease-in-out;
662
663    visibility: hidden;
664    opacity: 0;
665
666    padding: 5px;
667
668    display: flex;
669    flex-direction: row;
670    justify-content: center;
671    align-content: center;
672
673    line-height: 1.6;
674    word-wrap: break-word;
675    color: #fff;
676
677    border-bottom: 1px solid rgba(0, 0, 0, 0.9);
678}
679#noVNC_status.noVNC_open {
680    transform: translateY(0);
681    visibility: visible;
682    opacity: 1;
683}
684
685#noVNC_status::before {
686    content: "";
687    display: inline-block;
688    width: 25px;
689    height: 25px;
690    margin-right: 5px;
691}
692
693#noVNC_status.noVNC_status_normal {
694    background: rgba(128,128,128,0.9);
695}
696#noVNC_status.noVNC_status_normal::before {
697    content: url("../images/info.svg") " ";
698}
699#noVNC_status.noVNC_status_error {
700    background: rgba(200,55,55,0.9);
701}
702#noVNC_status.noVNC_status_error::before {
703    content: url("../images/error.svg") " ";
704}
705#noVNC_status.noVNC_status_warn {
706    background: rgba(180,180,30,0.9);
707}
708#noVNC_status.noVNC_status_warn::before {
709    content: url("../images/warning.svg") " ";
710}
711
712/* ----------------------------------------
713 * Connect dialog
714 * ----------------------------------------
715 */
716
717#noVNC_connect_dlg {
718    transition: 0.5s ease-in-out;
719
720    transform: scale(0, 0);
721    visibility: hidden;
722    opacity: 0;
723}
724#noVNC_connect_dlg.noVNC_open {
725    transform: scale(1, 1);
726    visibility: visible;
727    opacity: 1;
728}
729#noVNC_connect_dlg .noVNC_logo {
730    transition: 0.5s ease-in-out;
731    padding: 10px;
732    margin-bottom: 10px;
733
734    font-size: 80px;
735    text-align: center;
736
737    border-radius: 6px;
738}
739@media (max-width: 440px) {
740    #noVNC_connect_dlg {
741        max-width: calc(100vw - 100px);
742    }
743    #noVNC_connect_dlg .noVNC_logo {
744        font-size: calc(25vw - 30px);
745    }
746}
747#noVNC_connect_dlg div {
748    padding: 18px;
749
750    background-color: var(--novnc-darkgrey);
751    border-radius: 12px;
752    text-align: center;
753    font-size: 20px;
754
755    box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
756}
757#noVNC_connect_button {
758    width: 100%;
759    padding: 6px 30px;
760    cursor: pointer;
761    border-color: transparent;
762    border-radius: 12px;
763    background-color: var(--novnc-blue);
764    color: white;
765
766    display: flex;
767    justify-content: center;
768    place-items: center;
769    gap: 4px;
770}
771
772#noVNC_connect_button img {
773    vertical-align: bottom;
774    height: 1.3em;
775}
776
777/* ----------------------------------------
778 * Server verification dialog
779 * ----------------------------------------
780 */
781
782#noVNC_verify_server_dlg {
783    position: relative;
784
785    transform: translateY(-50px);
786}
787#noVNC_verify_server_dlg.noVNC_open {
788    transform: translateY(0);
789}
790#noVNC_fingerprint_block {
791    margin: 10px;
792}
793
794/* ----------------------------------------
795 * Password dialog
796 * ----------------------------------------
797 */
798
799#noVNC_credentials_dlg {
800    position: relative;
801
802    transform: translateY(-50px);
803}
804#noVNC_credentials_dlg.noVNC_open {
805    transform: translateY(0);
806}
807#noVNC_username_block.noVNC_hidden,
808#noVNC_password_block.noVNC_hidden {
809    display: none;
810}
811
812
813/* ----------------------------------------
814 * Main area
815 * ----------------------------------------
816 */
817
818/* Transition screen */
819#noVNC_transition {
820    transition: 0.5s ease-in-out;
821
822    display: flex;
823    opacity: 0;
824    visibility: hidden;
825
826    position: fixed;
827    top: 0;
828    left: 0;
829    bottom: 0;
830    right: 0;
831
832    color: white;
833    background: rgba(0, 0, 0, 0.5);
834    z-index: 50;
835
836    /*display: flex;*/
837    align-items: center;
838    justify-content: center;
839    flex-direction: column;
840}
841:root.noVNC_loading #noVNC_transition,
842:root.noVNC_connecting #noVNC_transition,
843:root.noVNC_disconnecting #noVNC_transition,
844:root.noVNC_reconnecting #noVNC_transition {
845    opacity: 1;
846    visibility: visible;
847}
848:root:not(.noVNC_reconnecting) #noVNC_cancel_reconnect_button {
849    display: none;
850}
851#noVNC_transition_text {
852    font-size: 1.5em;
853}
854
855/* Main container */
856#noVNC_container {
857    width: 100%;
858    height: 100%;
859    background-color: #313131;
860    border-bottom-right-radius: 800px 600px;
861    /*border-top-left-radius: 800px 600px;*/
862
863    /* If selection isn't disabled, long-pressing stuff in the sidebar
864       can accidentally select the container or the canvas. This can
865       happen when attempting to move the handle. */
866    user-select: none;
867    -webkit-user-select: none;
868}
869
870#noVNC_keyboardinput {
871    width: 1px;
872    height: 1px;
873    background-color: #fff;
874    color: #fff;
875    border: 0;
876    position: absolute;
877    left: -40px;
878    z-index: -1;
879    ime-mode: disabled;
880}
881
882/*Default noVNC logo.*/
883/* From: http://fonts.googleapis.com/css?family=Orbitron:700 */
884@font-face {
885    font-family: 'Orbitron';
886    font-style: normal;
887    font-weight: 700;
888    src: local('?'), url('Orbitron700.woff') format('woff'),
889                     url('Orbitron700.ttf') format('truetype');
890}
891
892.noVNC_logo {
893    color: var(--novnc-yellow);
894    font-family: 'Orbitron', 'OrbitronTTF', sans-serif;
895    line-height: 0.9;
896    text-shadow: 0.1em 0.1em 0 black;
897}
898.noVNC_logo span{
899    color: var(--novnc-green);
900}
901
902#noVNC_bell {
903    display: none;
904}
905
906/* ----------------------------------------
907 * Media sizing
908 * ----------------------------------------
909 */
910
911@media screen and (max-width: 640px){
912    #noVNC_logo {
913        font-size: 150px;
914    }
915}
916
917@media screen and (min-width: 321px) and (max-width: 480px) {
918    #noVNC_logo {
919        font-size: 110px;
920    }
921}
922
923@media screen and (max-width: 320px) {
924    #noVNC_logo {
925        font-size: 90px;
926    }
927}