Skip to content

Commit

Permalink
Use escape-svg() function (#29077)
Browse files Browse the repository at this point in the history
* Use escape-svg() function

* Update theming.md
  • Loading branch information
MartijnCuppens authored and mdo committed Jul 20, 2019
1 parent 28dfa54 commit f6694b7
Show file tree
Hide file tree
Showing 9 changed files with 51 additions and 31 deletions.
2 changes: 1 addition & 1 deletion scss/_breadcrumb.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
display: inline-block; // Suppress underlining of the separator in modern browsers
padding-right: $breadcrumb-item-padding-x;
color: $breadcrumb-divider-color;
content: $breadcrumb-divider;
content: escape-svg($breadcrumb-divider);
}
}

Expand Down
4 changes: 2 additions & 2 deletions scss/_carousel.scss
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,10 @@
background: no-repeat 50% / 100% 100%;
}
.carousel-control-prev-icon {
background-image: $carousel-control-prev-icon-bg;
background-image: escape-svg($carousel-control-prev-icon-bg);
}
.carousel-control-next-icon {
background-image: $carousel-control-next-icon-bg;
background-image: escape-svg($carousel-control-next-icon-bg);
}


Expand Down
11 changes: 11 additions & 0 deletions scss/_functions.scss
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,17 @@
@return $string;
}

// See https://codepen.io/kevinweber/pen/dXWoRw
@function escape-svg($string) {
@if str-index($string, "data:image/svg+xml") {
@each $char, $encoded in $escaped-characters {
$string: str-replace($string, $char, $encoded);
}
}

@return $string;
}

// Color contrast
@function color-yiq($color, $dark: $yiq-text-dark, $light: $yiq-text-light) {
$r: red($color);
Expand Down
4 changes: 2 additions & 2 deletions scss/_navbar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@
}

.navbar-toggler-icon {
background-image: $navbar-light-toggler-icon-bg;
background-image: escape-svg($navbar-light-toggler-icon-bg);
}

.navbar-text {
Expand Down Expand Up @@ -282,7 +282,7 @@
}

.navbar-toggler-icon {
background-image: $navbar-dark-toggler-icon-bg;
background-image: escape-svg($navbar-dark-toggler-icon-bg);
}

.navbar-text {
Expand Down
36 changes: 21 additions & 15 deletions scss/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ $yiq-contrasted-threshold: 150 !default;
$yiq-text-dark: $gray-900 !default;
$yiq-text-light: $white !default;

// Characters which are escaped by the escape-svg function
$escaped-characters: (
("<","%3c"),
(">","%3e"),
("#","%23"),
) !default;

// Options
//
Expand Down Expand Up @@ -531,32 +537,32 @@ $form-check-input-checked-border-color: $form-check-input-checked-bg-color !de
$form-check-input-checked-bg-repeat: no-repeat !default;
$form-check-input-checked-bg-position: center center !default;
$form-check-input-checked-bg-size: 1em !default;
$form-check-input-checked-bg-image: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath stroke='#{$form-check-input-checked-color}' stroke-width='3' d='M4 8.5L6.5 11l6-6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e"), "#", "%23") !default;
$form-check-radio-checked-bg-image: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='#{$form-check-input-checked-color}'/%3e%3c/svg%3e"), "#", "%23") !default;
$form-check-input-checked-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path stroke='#{$form-check-input-checked-color}' stroke-width='3' d='M4 8.5L6.5 11l6-6' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>") !default;
$form-check-radio-checked-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$form-check-input-checked-color}'/></svg>") !default;

$form-check-input-indeterminate-color: $component-active-color !default;
$form-check-input-indeterminate-bg-color: $component-active-bg !default;
$form-check-input-indeterminate-border-color: $form-check-input-indeterminate-bg-color !default;
$form-check-input-indeterminate-bg-repeat: no-repeat !default;
$form-check-input-indeterminate-bg-position: center center !default;
$form-check-input-indeterminate-bg-size: 1em !default;
$form-check-input-indeterminate-bg-image: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath d='M5 8h6' stroke='#{$form-check-input-indeterminate-color}' stroke-width='3' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e"), "#", "%23") !default;
$form-check-input-indeterminate-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path d='M5 8h6' stroke='#{$form-check-input-indeterminate-color}' stroke-width='3' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>") !default;

$form-switch-color: rgba(0, 0, 0, .25) !default;
$form-switch-width: 2em !default;
$form-switch-height: $form-check-input-width !default;
$form-switch-padding-left: $form-switch-width + .5em !default;
$form-switch-bg-image: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='#{$form-switch-color}'/%3e%3c/svg%3e"), "#", "%23") !default;
$form-switch-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$form-switch-color}'/></svg>") !default;
$form-switch-border-radius: $form-switch-width !default;
$form-switch-transition: .2s ease-in-out !default;
$form-switch-transition-property: background-position, background-color !default;

$form-switch-focus-color: hsla(211, 100%, 75%, 1) !default;
$form-switch-focus-bg-image: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='#{$form-switch-focus-color}'/%3e%3c/svg%3e"), "#", "%23") !default;
$form-switch-focus-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$form-switch-focus-color}'/></svg>") !default;

$form-switch-checked-color: $component-active-color !default;
$form-switch-checked-bg-image: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='#{$form-switch-checked-color}'/%3e%3c/svg%3e"), "#", "%23") !default;
$form-switch-checked-bg-position: right center !default;
$form-switch-checked-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$form-switch-checked-color}'/></svg>") !default;
$form-switch-checked-bg-position: right center !default;

$form-text-margin-top: .25rem !default;

Expand Down Expand Up @@ -586,9 +592,9 @@ $form-select-bg: $input-bg !default;
$form-select-disabled-bg: $gray-200 !default;
$form-select-bg-size: 16px 12px !default; // In pixels because image dimensions
$form-select-indicator-color: $gray-800 !default;
$form-select-indicator: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath stroke='#{$form-select-indicator-color}' stroke-width='2px' d='M2 5l6 6 6-6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e"), "#", "%23") !default;
$form-select-indicator: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path stroke='#{$form-select-indicator-color}' stroke-width='2px' d='M2 5l6 6 6-6' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>") !default;

$form-select-background: $form-select-indicator no-repeat right $form-select-padding-x center / $form-select-bg-size !default; // Used so we can have multiple background elements (e.g., arrow and feedback icon)
$form-select-background: no-repeat right $form-select-padding-x center / $form-select-bg-size !default; // Used so we can have multiple background elements (e.g., arrow and feedback icon)

$form-select-feedback-icon-padding-right: calc((1em + #{2 * $form-select-padding-y}) * 3 / 4 + #{$form-select-padding-x + $form-select-indicator-padding}) !default;
$form-select-feedback-icon-position: center right ($form-select-padding-x + $form-select-indicator-padding) !default;
Expand Down Expand Up @@ -659,9 +665,9 @@ $form-feedback-valid-color: theme-color("success") !default;
$form-feedback-invalid-color: theme-color("danger") !default;

$form-feedback-icon-valid-color: $form-feedback-valid-color !default;
$form-feedback-icon-valid: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"), "#", "%23") !default;
$form-feedback-icon-valid: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'><path fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/></svg>") !default;
$form-feedback-icon-invalid-color: $form-feedback-invalid-color !default;
$form-feedback-icon-invalid: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' stroke='#{$form-feedback-icon-invalid-color}' fill='none'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath d='M5.8 3.6h.4L6 6.5z' stroke-linejoin='round'/%3e%3ccircle cx='6' cy='8.2' r='.1'/%3e%3c/svg%3e"), "#", "%23") !default;
$form-feedback-icon-invalid: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' stroke='#{$form-feedback-icon-invalid-color}' fill='none'><circle cx='6' cy='6' r='4.5'/><path d='M5.8 3.6h.4L6 6.5z' stroke-linejoin='round'/><circle cx='6' cy='8.2' r='.1'/></svg>") !default;

$form-validation-states: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
Expand Down Expand Up @@ -737,14 +743,14 @@ $navbar-dark-color: rgba($white, .5) !default;
$navbar-dark-hover-color: rgba($white, .75) !default;
$navbar-dark-active-color: $white !default;
$navbar-dark-disabled-color: rgba($white, .25) !default;
$navbar-dark-toggler-icon-bg: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"), "#", "%23") !default;
$navbar-dark-toggler-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'><path stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/></svg>") !default;
$navbar-dark-toggler-border-color: rgba($white, .1) !default;

$navbar-light-color: rgba($black, .5) !default;
$navbar-light-hover-color: rgba($black, .7) !default;
$navbar-light-active-color: rgba($black, .9) !default;
$navbar-light-disabled-color: rgba($black, .3) !default;
$navbar-light-toggler-icon-bg: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"), "#", "%23") !default;
$navbar-light-toggler-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'><path stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/></svg>") !default;
$navbar-light-toggler-border-color: rgba($black, .1) !default;

$navbar-light-brand-color: $navbar-light-active-color !default;
Expand Down Expand Up @@ -1066,8 +1072,8 @@ $carousel-caption-color: $white !default;

$carousel-control-icon-width: 20px !default;

$carousel-control-prev-icon-bg: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e"), "#", "%23") !default;
$carousel-control-next-icon-bg: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e"), "#", "%23") !default;
$carousel-control-prev-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'><path d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/></svg>") !default;
$carousel-control-next-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'><path d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/></svg>") !default;

$carousel-transition-duration: .6s !default;
$carousel-transition: transform $carousel-transition-duration ease-in-out !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)
Expand Down
12 changes: 6 additions & 6 deletions scss/forms/_form-check.scss
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,17 @@
border-color: $form-check-input-checked-border-color;

&[type="checkbox"] {
background-image: $form-check-input-checked-bg-image;
background-image: escape-svg($form-check-input-checked-bg-image);
}

&[type="radio"] {
background-image: $form-check-radio-checked-bg-image;
background-image: escape-svg($form-check-radio-checked-bg-image);
}
}

&[type="checkbox"]:indeterminate {
background-color: $form-check-input-indeterminate-bg-color;
background-image: $form-check-input-indeterminate-bg-image;
background-image: escape-svg($form-check-input-indeterminate-bg-image);
background-repeat: $form-check-input-indeterminate-bg-repeat;
background-position: $form-check-input-indeterminate-bg-position;
background-size: $form-check-input-indeterminate-bg-size;
Expand Down Expand Up @@ -90,7 +90,7 @@
.form-check-input {
width: $form-switch-width;
margin-left: $form-switch-padding-left * -1;
background-image: $form-switch-bg-image;
background-image: escape-svg($form-switch-bg-image);
background-repeat: no-repeat;
background-position: left center;
background-size: calc(#{$form-switch-height} - 2px); // Get a 1px separation
Expand All @@ -100,11 +100,11 @@
// transition-property: $form-switch-transition-property;

&:focus {
background-image: $form-switch-focus-bg-image;
background-image: escape-svg($form-switch-focus-bg-image);
}

&:checked {
background-image: $form-switch-checked-bg-image;
background-image: escape-svg($form-switch-checked-bg-image);
background-position: $form-switch-checked-bg-position;
}
}
Expand Down
3 changes: 1 addition & 2 deletions scss/forms/_form-select.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
line-height: $form-select-line-height;
color: $form-select-color;
vertical-align: middle;
background: $form-select-background;
background-color: $form-select-bg;
background: $form-select-bg escape-svg($form-select-indicator) $form-select-background;
border: $form-select-border-width solid $form-select-border-color;
@include border-radius($form-select-border-radius, 0);
@include box-shadow($form-select-box-shadow);
Expand Down
4 changes: 2 additions & 2 deletions scss/mixins/_forms.scss
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@

@if $enable-validation-icons {
padding-right: $input-height-inner;
background-image: $icon;
background-image: escape-svg($icon);
background-repeat: no-repeat;
background-position: right $input-height-inner-quarter center;
background-size: $input-height-inner-half $input-height-inner-half;
Expand Down Expand Up @@ -103,7 +103,7 @@

@if $enable-validation-icons {
padding-right: $form-select-feedback-icon-padding-right;
background: $form-select-background, $icon $form-select-bg no-repeat $form-select-feedback-icon-position / $form-select-feedback-icon-size;
background: escape-svg($form-select-indicator) $form-select-background, escape-svg($icon) $form-select-bg no-repeat $form-select-feedback-icon-position / $form-select-feedback-icon-size;
}

&:focus {
Expand Down
6 changes: 5 additions & 1 deletion site/content/docs/4.3/getting-started/theming.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ Additional functions could be added in the future or your own custom Sass to cre

### Color contrast

One additional function we include in Bootstrap is the color contrast function, `color-yiq`. It utilizes the [YIQ color space](https://en.wikipedia.org/wiki/YIQ) to automatically return a light (`#fff`) or dark (`#111`) contrast color based on the specified base color. This function is especially useful for mixins or loops where you're generating multiple classes.
An additional function we include in Bootstrap is the color contrast function, `color-yiq`. It utilizes the [YIQ color space](https://en.wikipedia.org/wiki/YIQ) to automatically return a light (`#fff`) or dark (`#111`) contrast color based on the specified base color. This function is especially useful for mixins or loops where you're generating multiple classes.

For example, to generate color swatches from our `$theme-colors` map:

Expand Down Expand Up @@ -223,6 +223,10 @@ You can also specify a base color with our color map functions:
}
{{< /highlight >}}

## Escape SVG

We use the `escape-svg` function to escape the `<`, `>` and `#` characters for SVG background images. These characters need to be escaped to properly render the background images in IE.

## Sass options

Customize Bootstrap 4 with our built-in custom variables file and easily toggle global CSS preferences with new `$enable-*` Sass variables. Override a variable's value and recompile with `npm run test` as needed.
Expand Down

0 comments on commit f6694b7

Please sign in to comment.