|
| 1 | +// Copyright 2013 The Flutter Authors. All rights reserved. |
| 2 | +// Use of this source code is governed by a BSD-style license that can be |
| 3 | +// found in the LICENSE file. |
| 4 | + |
| 5 | +import 'browser_detection.dart'; |
| 6 | +import 'dom.dart'; |
| 7 | +import 'text_editing/text_editing.dart'; |
| 8 | + |
| 9 | +// Applies the required global CSS to an incoming [DomCSSStyleSheet] `sheet`. |
| 10 | +void applyGlobalCssRulesToSheet( |
| 11 | + DomHTMLStyleElement styleElement, { |
| 12 | + required bool hasAutofillOverlay, |
| 13 | + String cssSelectorPrefix = '', |
| 14 | + required String defaultCssFont, |
| 15 | +}) { |
| 16 | + // TODO(web): use more efficient CSS selectors; descendant selectors are slow. |
| 17 | + // More info: https://csswizardry.com/2011/09/writing-efficient-css-selectors |
| 18 | + |
| 19 | + assert(styleElement.sheet != null); |
| 20 | + final DomCSSStyleSheet sheet = styleElement.sheet! as DomCSSStyleSheet; |
| 21 | + |
| 22 | + // These are intentionally outrageous font parameters to make sure that the |
| 23 | + // apps fully specify their text styles. |
| 24 | + // |
| 25 | + // Fixes #115216 by ensuring that our parameters only affect the flt-scene-host children. |
| 26 | + sheet.insertRule(''' |
| 27 | + $cssSelectorPrefix flt-scene-host { |
| 28 | + color: red; |
| 29 | + font: $defaultCssFont; |
| 30 | + } |
| 31 | + ''', sheet.cssRules.length); |
| 32 | + |
| 33 | + // By default on iOS, Safari would highlight the element that's being tapped |
| 34 | + // on using gray background. This CSS rule disables that. |
| 35 | + if (isSafari) { |
| 36 | + sheet.insertRule(''' |
| 37 | + $cssSelectorPrefix * { |
| 38 | + -webkit-tap-highlight-color: transparent; |
| 39 | + } |
| 40 | + ''', sheet.cssRules.length); |
| 41 | + } |
| 42 | + |
| 43 | + if (isFirefox) { |
| 44 | + // For firefox set line-height, otherwise text at same font-size will |
| 45 | + // measure differently in ruler. |
| 46 | + // |
| 47 | + // - See: https://github.com/flutter/flutter/issues/44803 |
| 48 | + sheet.insertRule(''' |
| 49 | + $cssSelectorPrefix flt-paragraph, |
| 50 | + $cssSelectorPrefix flt-span { |
| 51 | + line-height: 100%; |
| 52 | + } |
| 53 | + ''', sheet.cssRules.length); |
| 54 | + } |
| 55 | + |
| 56 | + // This undoes browser's default painting and layout attributes of range |
| 57 | + // input, which is used in semantics. |
| 58 | + sheet.insertRule(''' |
| 59 | + $cssSelectorPrefix flt-semantics input[type=range] { |
| 60 | + appearance: none; |
| 61 | + -webkit-appearance: none; |
| 62 | + width: 100%; |
| 63 | + position: absolute; |
| 64 | + border: none; |
| 65 | + top: 0; |
| 66 | + right: 0; |
| 67 | + bottom: 0; |
| 68 | + left: 0; |
| 69 | + } |
| 70 | + ''', sheet.cssRules.length); |
| 71 | + |
| 72 | + if (isSafari) { |
| 73 | + sheet.insertRule(''' |
| 74 | + $cssSelectorPrefix flt-semantics input[type=range]::-webkit-slider-thumb { |
| 75 | + -webkit-appearance: none; |
| 76 | + } |
| 77 | + ''', sheet.cssRules.length); |
| 78 | + } |
| 79 | + |
| 80 | + // The invisible semantic text field may have a visible cursor and selection |
| 81 | + // highlight. The following 2 CSS rules force everything to be transparent. |
| 82 | + sheet.insertRule(''' |
| 83 | + $cssSelectorPrefix input::selection { |
| 84 | + background-color: transparent; |
| 85 | + } |
| 86 | + ''', sheet.cssRules.length); |
| 87 | + sheet.insertRule(''' |
| 88 | + $cssSelectorPrefix textarea::selection { |
| 89 | + background-color: transparent; |
| 90 | + } |
| 91 | + ''', sheet.cssRules.length); |
| 92 | + |
| 93 | + sheet.insertRule(''' |
| 94 | + $cssSelectorPrefix flt-semantics input, |
| 95 | + $cssSelectorPrefix flt-semantics textarea, |
| 96 | + $cssSelectorPrefix flt-semantics [contentEditable="true"] { |
| 97 | + caret-color: transparent; |
| 98 | + } |
| 99 | + ''', sheet.cssRules.length); |
| 100 | + |
| 101 | + // Hide placeholder text |
| 102 | + sheet.insertRule(''' |
| 103 | + $cssSelectorPrefix .flt-text-editing::placeholder { |
| 104 | + opacity: 0; |
| 105 | + } |
| 106 | + ''', sheet.cssRules.length); |
| 107 | + |
| 108 | + // This CSS makes the autofill overlay transparent in order to prevent it |
| 109 | + // from overlaying on top of Flutter-rendered text inputs. |
| 110 | + // See: https://github.com/flutter/flutter/issues/118337. |
| 111 | + if (browserHasAutofillOverlay()) { |
| 112 | + sheet.insertRule(''' |
| 113 | + $cssSelectorPrefix .transparentTextEditing:-webkit-autofill, |
| 114 | + $cssSelectorPrefix .transparentTextEditing:-webkit-autofill:hover, |
| 115 | + $cssSelectorPrefix .transparentTextEditing:-webkit-autofill:focus, |
| 116 | + $cssSelectorPrefix .transparentTextEditing:-webkit-autofill:active { |
| 117 | + opacity: 0 !important; |
| 118 | + } |
| 119 | + ''', sheet.cssRules.length); |
| 120 | + } |
| 121 | + |
| 122 | + // Removes password reveal icon for text inputs in Edge browsers. |
| 123 | + // Non-Edge browsers will crash trying to parse -ms-reveal CSS selector, |
| 124 | + // so we guard it behind an isEdge check. |
| 125 | + // Fixes: https://github.com/flutter/flutter/issues/83695 |
| 126 | + if (isEdge) { |
| 127 | + // We try-catch this, because in testing, we fake Edge via the UserAgent, |
| 128 | + // so the below will throw an exception (because only real Edge understands |
| 129 | + // the ::-ms-reveal pseudo-selector). |
| 130 | + try { |
| 131 | + sheet.insertRule(''' |
| 132 | + $cssSelectorPrefix input::-ms-reveal { |
| 133 | + display: none; |
| 134 | + } |
| 135 | + ''', sheet.cssRules.length); |
| 136 | + } on DomException catch (e) { |
| 137 | + // Browsers that don't understand ::-ms-reveal throw a DOMException |
| 138 | + // of type SyntaxError. |
| 139 | + domWindow.console.warn(e); |
| 140 | + // Add a fake rule if our code failed because we're under testing |
| 141 | + assert(() { |
| 142 | + sheet.insertRule(''' |
| 143 | + $cssSelectorPrefix input.fallback-for-fakey-browser-in-ci { |
| 144 | + display: none; |
| 145 | + } |
| 146 | + ''', sheet.cssRules.length); |
| 147 | + return true; |
| 148 | + }()); |
| 149 | + } |
| 150 | + } |
| 151 | +} |
0 commit comments