@use "sass:map"; @use "metadata" as *; :root { //* rgba is needed for the selected country hover state to blend in with the border-highlighting some browsers give the input on focus. --iti-hover-color: rgba(0, 0, 0, 0.05); //* Used as the bg color for both the selected country and the dropdown items, on hover. --iti-border-color: #ccc; //* Used for both the dropdown border, and the divider under the country search input. --iti-dialcode-color: #999; --iti-dropdown-bg: white; //* icons include: arrow icon, globe icon (selected country empty state), search magnifying glass icon, search clear icon --iti-icon-color: #555; --iti-spacer-horizontal: 8px; --iti-flag-height: #{$flag-height}; --iti-flag-width: #{$flag-width}; //* Separate height for the globe icon, as it's much thinner than the flags, so nice to have it a bit taller. This is also re-used for the search icon. --iti-globe-height: 16px; //* Separate height for the search clear icon, which looks too big if it's the same as the others. --iti--search-clear-icon-height: 13px; //* This border width is used for the popup and divider, but it is also assumed to be the border width of the input, which we do not control. --iti-border-width: 1px; //* Arrow height must be an even number as it gets halved when calculating arrow width --iti-arrow-height: 4px; --iti-arrow-width: calc((var(--iti-arrow-height) / 2) * 3); --iti-triangle-border: calc(var(--iti-arrow-width) / 2); --iti-arrow-padding: 6px; //* NOTE: image paths are now defined in intlTelInputWithAssets.scss --iti-flag-sprite-width: #{map.get($flags-sprite-1x, width)}; --iti-flag-sprite-height: #{map.get($flags-sprite-1x, height)}; //* Enough space for them to click off to close. --iti-mobile-popup-margin: 30px; } .iti { //* We need position on the container so the selected country can be absolutely positioned over the input. position: relative; //* Keep the input's default inline properties. display: inline-block; //* Paul Irish (paulirish) says this is ok. //* http://www.paulirish.com/2012/box-sizing-border-box-ftw/ * { box-sizing: border-box; } &__a11y-text { width: 1px; height: 1px; clip: rect(1px, 1px, 1px, 1px); overflow: hidden; position: absolute; } //* Specify types to increase specificity e.g. to override bootstrap v2.3. input.iti__tel-input, input.iti__tel-input[type="text"], input.iti__tel-input[type="tel"] { position: relative; //* Input is bottom level, below selected country and dropdown. z-index: 0; //* Since we wrap the input in a container div, any margin here would interfere with the positioning of the selected country. margin: 0 !important; } &__country-container { //* Positioned over the top of the input. position: absolute; //* Full height. top: 0; bottom: 0; left: 0; //* Prevent the highlighted child from overlapping the input border. padding: var(--iti-border-width); } //* Now a button element. &__selected-country { //* Render above the input. z-index: 1; position: relative; display: flex; align-items: center; //* This must be full-height both for the hover highlight, and to push down the dropdown so it appears below the input. height: 100%; //* Reset button styles (can't use all:unset as lose browser default focus outline styles). background: none; border: 0; margin: 0; padding: 0; font-family: inherit; font-size: inherit; color: inherit; border-radius: 0; font-weight: inherit; line-height: inherit; text-decoration: none; } &__selected-country-primary { display: flex; align-items: center; //* This must be full-height for the hover highlight. height: 100%; padding: 0 var(--iti-arrow-padding) 0 var(--iti-spacer-horizontal); } &__arrow { margin-left: var(--iti-arrow-padding); //* CSS triangle. width: 0; height: 0; border-left: var(--iti-triangle-border) solid transparent; border-right: var(--iti-triangle-border) solid transparent; border-top: var(--iti-arrow-height) solid var(--iti-icon-color); &--up { border-top: none; border-bottom: var(--iti-arrow-height) solid var(--iti-icon-color); } } //* The dropdown. &__dropdown-content { border-radius: 3px; background-color: var(--iti-dropdown-bg); .iti--inline-dropdown & { position: absolute; //* Popup so render above everything else. z-index: 2; //* Since (sometimes) adding a search input in the dropdown, better to make the dropdown look a bit more distinct from the tel input, to reduce confusion between the two inputs. margin-top: 3px; //* margin-left to compensate for the padding on the parent. margin-left: calc(var(--iti-border-width) * -1); border: var(--iti-border-width) solid var(--iti-border-color); box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.2); } } &__search-input { width: 100%; border-width: 0; border-radius: 3px; padding-left: 30px; //* Space for inline search icon. padding-right: 28px; //* Space for clear button. //* RTL: put the icon on the right instead. [dir="rtl"] & { padding-left: inherit; padding-right: 30px; background-position: right 8px center; } & + .iti__country-list { border-top: 1px solid var(--iti-border-color); } // hide chrome/safari's native clear button for inputs with type=search &::-webkit-search-cancel-button { appearance: none; } } &__search-input-wrapper { position: relative; display: flex; align-items: center; } &__search-icon { position: absolute; left: 8px; display: flex; pointer-events: none; } [dir="rtl"] &__search-icon { left: auto; right: 8px; } &__search-icon-svg { width: var(--iti-globe-height); height: var(--iti-globe-height); display: block; stroke: var(--iti-icon-color); fill: none; stroke-width: 3; } &__search-clear { position: absolute; right: 4px; background: transparent; border: 0; border-radius: 3px; // nice on hover state cursor: pointer; padding: 5px; display: flex; align-items: center; justify-content: center; transition: background-color 0.15s ease; .iti__search-clear-x { stroke-width: 2; } .iti__search-clear-bg { fill: var(--iti-icon-color); } } &__search-clear-svg { width: var(--iti--search-clear-icon-height); height: var(--iti--search-clear-icon-height); display: block; } [dir="rtl"] &__search-clear { right: auto; left: 4px; } &__search-clear:hover, &__search-clear:focus-visible { background: var(--iti-hover-color); outline: none; } &__no-results { text-align: center; padding: 30px 0; } &__country-list { //* Override default list styles. list-style: none; padding: 0; margin: 0; cursor: pointer; overflow-y: scroll; //* Fixes https://github.com/jackocnr/intl-tel-input/issues/765 //* Apple still hasn't fixed the issue where setting overflow: scroll on a div element does not use inertia scrolling //* If this is not set, then the country list scroll stops moving after raising a finger, and users report that scroll is slow //* Stackoverflow question about it: https://stackoverflow.com/questions/33601165/scrolling-slow-on-mobile-ios-when-using-overflowscroll -webkit-overflow-scrolling: touch; .iti--inline-dropdown & { max-height: 185px; } } &--flexible-dropdown-width &__country-list { //* Don't let the contents wrap AKA the container will be as wide as the contents. white-space: nowrap; //* Except on small screens, where we force the dropdown width to match the input. @media (max-width: 500px) { white-space: normal; } } //* Each country item in dropdown (we must have separate class to differentiate from dividers). &__country { //* Note: decided not to use line-height here for alignment because it causes issues e.g. large font-sizes will overlap, and also looks bad if one country overflows onto 2 lines. display: flex; align-items: center; padding: 8px var(--iti-spacer-horizontal); outline: none; } //* Check icon shown on the right for the selected country. &__country-check { // align with clear icon which has padding:5px and right:4px, so is 9px from right edge // here, the parent list item has padding:8px, so add 1px to make it 9px from right edge margin: 0 1px 0 auto; display: flex; align-items: center; color: var(--iti-icon-color); } &__country-check-svg { width: var(--iti--search-clear-icon-height); height: var(--iti--search-clear-icon-height); display: block; } //* The grey dial codes, displayed after the country names in the dropdown. &__dial-code { margin-left: var(--iti-spacer-horizontal); color: var(--iti-dialcode-color); [dir="rtl"] & { margin-left: 0; margin-right: var(--iti-spacer-horizontal); } } &__country.iti__highlight { background-color: var(--iti-hover-color); } //* Spacing between country flag, name and dial code. &__country-list .iti__flag, &__country-name { margin-right: var(--iti-spacer-horizontal); [dir="rtl"] & { margin-right: 0; margin-left: var(--iti-spacer-horizontal); } } &__country-list .iti__flag { flex-shrink: 0; // stop long country names from shrinking the flag } &--allow-dropdown { //* Hover state - show country is clickable (unless the input is disabled or readonly) .iti__country-container:not(:has(+ input[disabled])):not(:has(+ input[readonly])) { button.iti__selected-country { cursor: pointer; } //* Only show hover background colour when you hover (1) selected flag/arrow or (2) dropdown contents, but NOT when you hover the selected dial code, which would feel weird. .iti__selected-country-primary:hover, .iti__selected-country:has(+ .iti__dropdown-content:hover) .iti__selected-country-primary { background-color: var(--iti-hover-color); } } } .iti__selected-dial-code { margin-left: 4px; } //* If dropdownContainer option is set, increase z-index to prevent display issues. &--container { position: fixed; top: -1000px; left: -1000px; //* Higher than default Bootstrap modal z-index of 1050. z-index: 1060; //* To keep styling consistent with .country-container. padding: var(--iti-border-width); &:hover { cursor: pointer; } } // put these at the end, so they override other classes with display:flex etc &__hide { display: none; } //* Need this during init, to get the height of the dropdown. &__v-hide { visibility: hidden; } } //* Overrides for mobile popup. .iti--fullscreen-popup { &.iti--container { background-color: rgba(0, 0, 0, 0.5); top: 0; bottom: 0; left: 0; right: 0; position: fixed; padding: var(--iti-mobile-popup-margin); //* Short country lists should be vertically centred. display: flex; flex-direction: column; //* The country search input auto-focuses, so mobile keyboard appears, so stick to top (also because when filter countries down, the height changes and the vertical centring would make it jump around). justify-content: flex-start; } .iti__dropdown-content { display: flex; flex-direction: column; max-height: 100%; position: relative; //* Override needed in order to get full-width working properly. } .iti__country { padding: 10px 10px; //* Increase line height because dropdown copy is v likely to overflow on mobile and when it does it needs to be well spaced. line-height: 1.5em; } } .iti__flag { //* Start with an offset to hide any flags. This is useful to show an empty state (with correct dimensions) while geoIpLookup is loading. --iti-flag-offset: 100px; height: var(--iti-flag-height); width: var(--iti-flag-width); border-radius: 1px; box-shadow: 0px 0px 1px 0px #888; background-image: image-set( var(--iti-path-flags-1x) 1x, var(--iti-path-flags-2x) 2x ); background-repeat: no-repeat; background-position: var(--iti-flag-offset) 0; background-size: var(--iti-flag-sprite-width) var(--iti-flag-sprite-height); } //* Loading state (used while geoIpLookup is resolving auto country). .iti__loading { position: relative; background: none; box-shadow: none; } .iti__loading::after { content: ""; position: absolute; inset: 0; margin: auto; width: var(--iti-flag-height); height: var(--iti-flag-height); box-sizing: border-box; border: 2px solid var(--iti-icon-color); border-right-color: transparent; border-radius: 50%; animation: iti-spinner 1s linear infinite; } @keyframes iti-spinner { to { transform: rotate(360deg); } } @each $country-code, $values in $flags { $flag-offset: map.get($values, offset); .iti__#{$country-code} { --iti-flag-offset: #{$flag-offset}; } } //* Empty state. // Inline globe icon (now rendered as SVG inside .iti__flag). Keep class for width/position logic and to clear box-shadow. .iti__globe { background: none; box-shadow: none; height: var(--iti-globe-height); display: flex; align-items: center; justify-content: center; padding: 0; // ensure svg centers .iti__globe-svg { width: 100%; height: 100%; fill: var(--iti-icon-color); } } /* Browsers normally add a coloured outline when you focus an input. Chrome adds a blue outline WITHIN the input. If you focus the input and then hover the selected country, it's bg color square overlaps the focus outline and looks bad. Here, @supports is used to target Chrome only, and move the default outline out by 1px so there's no overlap. */ @supports (-webkit-appearance:none) and (not (background: -webkit-canvas(foo))) { .iti__tel-input:focus { outline-offset: 1px; } }