Bootstrap front-end framerwork
Contents |
Bootstrap 4
Bootstrap
div
is block element and by default it will be stacked. Bootstrap grid is
mobile first, so three .col-md-4
will be stacked until desktop, so on desktop,
large and extra large desktop it will be like three equal width columns. You do
not need to define all 12, .col
will occupy rest of place. .col-auto
will
occupy only that is needed (based on it’s contents, it uses max-width: 100%
).
When you specify for sm, you do not need to specify for md or lg. col-xs-12
is
width: 100%
which is default so no need to write that. Write only when you
need columns. Gutter between columns (padding) is 30px, ie 15px on each side,
so when nesting column inside column, first column will get blank space on its
left (unneeded indent from 15px padding from first column and 15px padding from
nested column) so that the reason why row has -15px margin (to fix eventual
parent column padding) and you have to wrap row with .container
class to
compensate that (padding 15px) or to add class px-3
, otherwise you will get
horizontal scrollbar since body will be larger than 100% by 30px.
Also for .container-fluid
Bootstrap Media queries:
- xs - phones (no need for media queary since this is default)
- sm - tablets
@media (min-width: map-get($grid-breakpoints, 'sm') { // 576px (Bv3 768px) and up
- md - desktops
@media (min-width: @screen-md-min) { // 768px (Bv3 992px)
- lg - larger desktops
@media (min-width: @screen-lg-min) { // 992px (Bv3 1200px)
- xl - extra lage
@media (min-width: @screen-xl-min) { // 1200pxa
With bootstrap 4 you can use mixins for media queries:
// given (sm) and larger
@include media-breakpoint-up(sm) {
.some-class {
display: block;
// or other direction (given and smaller)
@include media-breakpoint-down(sm) {}
// only given size
@include media-breakpoint-only(sm) {}
// multiple sizes
@include media-breakpoint-between(md, xl) {}
@media (min-width: 768px) and (max-width: 1199.98px) { ... }
With Bootstrap3 you can use their predefined media queries with min-width
(mobile first), for example
@media(min-width:$screen-sm){
.alert {
position: absolute;
bottom: 0px;
right: 20px;
}
}
// or in other direction (given and smaller)
@media(max-width: $screen-sm) { }
// or better do not use boundary
@media(max-width: 575.98px) { }
Bootstrap container
has fixed width for big devices.
Difference with bootstrap 3 is that there is new grid tier xl
that was lg
in
B3 (sm
is 576px instead of 768px in B3) and all are bumped up one level (so
.col-md-6
in v3 is now .col-lg-6
in v4)
Boostrap 3 you can use responsive available
classes to toggle
between display: block, inline, inline-block
or to hide, for specific viewport
size .visibe-sm-block .hidden-md .hidden-sm-up
In Bootstrap 4 you can use d-*-none
class
https://getbootstrap.com/docs/4.1/utilities/display/
To hide on smaller than md (ie show on md and larger) use d-none d-md-block
To show only on md use .d-none .d-md-block .d-lg-none
You can write your own to match all greater (or smaller) sizes:
# when it is max-width than it is Non-Mobile First Method
# so we use le (less or equal then)
# (min-width is Mobile First and we use hide-ge-)
/* Large Devices, Wide Screens */
@media only screen and (max-width : 1200px) {
.hide-le-lg {
display: none;
}
}
/* Medium Devices, Desktops */
@media only screen and (max-width : 992px) {
.hide-le-md {
display: none;
}
}
/* Small Devices, Tablets */
@media only screen and (max-width : 768px) {
.hide-le-sm {
display: none;
}
}
/* Extra Small Devices, Phones */
@media only screen and (max-width : 480px) {
.hide-le-xs {
display: none;
}
}
- you can center bootstrap column with offset
- you can set icons on inputs, easy with generators, just add
prepend: 'password'
Bootstrap modal
On B3 you can use ajax and render layout: false
and provide only inner html of
<div class="modal"><div class="modal-dialog">...
ie only .modal-content
will
be replaced. So you should use same header and footer in initial and ajax
version.
On B4 we need to replace the modal content with custom js, so I use jBox modal in this case.
To close modal with escape key you need to add tabindex on modal elemenent:
<div class="modal" tabindex="-1">
. Note that on Firefox ESC closing modal
works without this tabindex attribute. Note also that select2 dows
On activation button you do not need data-keyboard="true"
since that is
default. But remove data-keyboard="false"
if exists and you want to close
modal with escape key.
You can use autofocus="true"
option to focus input field when modal shows up.
For tooltips you can use html
version data-html="true" data-toggle="tooltip" title="<h2>Hi</h2>"
.
If you use ajax than modal content is cached, you can clear that cache on shown or hidden event (or in ajax response). Note that inline javascript will not be run again, cached content will be cleared (and modal will be loaded again) but new javascript will not be run for the same url… Actually it does not run tags in subsequent runs (only on first fetch).
<script>
$('#assign-location-modal').on('shown.bs.modal', function () {
$(this).removeData('bs.modal');
});
</script>
# or for all, for example in document_on.coffee
$(document).on 'hidden.bs.modal', '.modal', ->
$(this).removeData('bs.modal')
console.log "remove boostrap modal"
You can hide close modal with $('#my-modal').modal('toggle');
Usually fade
makes some problem with positioning so you should not use fadding
for custom modals.
Bootstrap tooltip
To inspect data-toggle="tooltip"
you need to find it’s selector and
manually call $('.myel').tooltip("show");
or in developer tools when you
select <a title=
element you can reference it with $0
so command is
$($0).tooltip("show")
or you can increase delay for hide
$('[data-toggle="tooltip"]').tooltip(
delay:
hide: 100000
)
If it is inside element with overflow-y: scroll;
than it won’t be seen if it
goes over borders. You need to change container of the tooltip. You can do it
simply for all tooptips by overwriting DEFAULTS (if you need more customization,
you can overwrite any prototype of the class)
$.fn.tooltip.Constructor.DEFAULTS.container = 'body'
$.fn.tooltip.Constructor.DEFAULTS.placement = 'right'
Bootstrap input group and button group
Buttons and inputs can be grouped, but input group is not advised to group with select. Here is example of input with select and button.
Helpers
Color helpers
Primary colors are link
primary
, secondary
, success
, danger
, warning
, info
, dark
, light
,
white
. For text there is muted
. Background bg-dark text-light
. There is a border corols border-white
.
You can set default body background by defining variable $body-bg: #bcdee3
before importing boostrap.
You can use css darken
for example for variable
$link-hover-color: darken($link-color, 15%) !default;
https://github.com/twbs/bootstrap/blob/e7e43edf65306efaf46a16ffc9fe35ef623bffef/scss/_variables.scss#L171
- text and links
.text-success
- background
.bg-warning
- buttons
.btn-primary
- borders
.border-primary
(border border-top-0
to disable,rounded-pill
to add radius to border)
Other helpers are:
- position helpers
position-relative
,position-absolute
https://github.com/twbs/bootstrap/blob/e57a2f244ba8446fffe71847e6a58b18f7b2d541/scss/utilities/_position.scss .clearfix
- text size
.h1
(2.5rem),.h2
(2rem),.h3
(1.75rem),.h4
(1.5rem),.h5
(1.25rem),.h6
(1rem) so you can useh2
instead definingfont-size-2
font-weight-bold
to use bold font- text position
.text-center
,.text-left
,.text-nowrap
https://www.w3schools.com/bootstrap/bootstrap_ref_css_text.asp text-truncate
withmax-width: 100px
https://getbootstrap.com/docs/4.1/utilities/text/#text-wrapping-and-overflow.show
and.hidden
.d-none
to hide something. But when I want to show/hide in js I usually create my own.d-none-not-important
since bootstrap’s is withimportant
. I usedhide-not-important
with jQuery$el.show()
(hide) or$el.slideDown()
(slideUp) but they usedisplay: block
which does not work well withdisplay: flex
elements, better is to use$(el).addClass('d-none-not-important')
. There is also hidden
# app/assets/stylesheets/common/show_hide.sass
.d-none-not-important,.hide-not-important
visibility: hidden
opacity: 0
transition: visibility 0.5s ease, opacity 0.5s ease
// display: none
&.active
visibility: visible
opacity: 1
// display: initial
-
margin and padding helpers in format
<property><sides>-<breakpoint>-<size>
https://getbootstrap.com/docs/4.0/utilities/spacing/#notation property ism
margin orp
padding sidest
top,b
bottom,l
left,r
right,x
both l and r,y
t and b size0
,1
($spacer * 0.25
),2
($spacer * .5
),3
($spacer
),4
($spacer * 1.5
),5
($spacer * 3
), By default$spacer: 1rem
1rem is default font size ie 16px on B4 (1.5 line height) and 14px in B3 (1.428 line height)mx-auto
formargin: 0px auto
. sides or breakpoint not required:p-0
padding none,mt-5
margin top, but you can usemb-lg-5
. Note that margins are not applicable ford-inline
elements.For inline elements you can use
float-left
(instead ofpull-left
). For block elements with fixed widthml-auto
to align to the right (same as pull-right in B3),mx-auto
for horizontal centering (need fixed width). For block elements that are by default 100% width, you can wrap insided-flex w-100 justify-content-between
width 100% is important because you want right element to go right. https://getbootstrap.com/docs/4.0/components/list-group/#custom-content (alsojustify-content-around justify-content-center justify-content-start
).For cross axis it will be scretched so use
d-flex align-items-center
to center verticaly (or horizontaly if it is column based). You can also align for particular itemalign-self-center
. Grow item withflex-grow-1
orflex-shrink-1
. d-flex
class to convert to flexbox container. You can change display withd-inline
,d-inline-block
. Other flex helpers https://getbootstrap.com/docs/4.0/utilities/flex/ for example to enable wrap used-flex flex-wrap
. You can use those classes instead of row col. For example<div class='d-flex flex-column flex-md-row'> <div></div> <div></div> </div> is similar to <div class='row'> <div class='col-md-6'></div> <div class='col-md-6'></div> </div> but it will be justify-content-start(so no padding around columns )and size is depending on the content (not 50% as in col-6)
dl-horizontal
can be replaces with<dl class='row justify-content-start'> <dt class='col-sm-2'>Sign In Count</dt> <dd class='col'><%= @user.sign_in_count %></dd> <dt class='w-100'></dt> <dt class='col-sm-2'>Last Sign In at</dt> <dd class='col'><%= @user.last_sign_in_at.to_s :short %></dd> <dt class='w-100'></dt> </dl>
- to use variable unkown number of columns with multi line you can insert
.w-100
where you want on specific responsive (for example on md you can insert after every 6 columnts) https://getbootstrap.com/docs/4.4/layout/grid/#equal-width-multi-line<div class="container"> <div class="row"> <div class="col">col</div> <div class="col">col</div> <div class="w-100"></div> <div class="col">col</div> <div class="col">col</div> </div> </div>
Btw there are helpers for max-width
.mw-100
, view port.vh-100
(heigh: 100vh
).another way is to use row-cols https://getbootstrap.com/docs/4.4/layout/grid/#row-columns
<div class="container"> <div class="row row-cols-2"> <div class="col">Column</div> <div class="col">Column</div> <div class="col">Column</div> <div class="col">Column</div> </div> </div>
Rails
Overrides
There are two files that configure and override bootstrap
# app/stylesheets/application.sass
// default
@import 'common/variable_default_values'
// node_modules
@import 'bootstrap/scss/bootstrap'
// common
@import 'common/variables'
@import 'common/bootstrap_overrides'
# app/assets/stylesheets/common/bootstrap_overrides
// it is not actually overrides, but additional classes that modify existing
// this is used if you want btn inside h1
.btn.btn__font-size-inherit
font-size: inherit
.btn.btn__text_wrap
white-space: normal
Nabar
https://getbootstrap.com/docs/4.0/examples/navbars/ shows different styles
Here is an example adding style for specific media for alert
// app/assets/stylesheets/common.scss
@import "bootstrap-variables";
.hidden-left {
position: absolute;
left: -1000px;
}
@media(min-width:$screen-sm){
.alert {
position: absolute;
top: 8px;
padding: 8px;
padding-right: 30px; // close sign
z-index: 9999;
left: 480px; // enought to see nav buttons
}
}
Still, default rails form build will render field_with_errors
on label and
input wrap, so if you need to change for bootstrap error classes.
Note that with Bootstrap 3, you have to change control-group
to form-group
,
add form-control
to <input>
elements, help-inline
to help-block
, and
warning
to has-warning
or error
to has-error
.
The easiest approach is with bootstrap form.
Bootstrap form
bootstrap_form gem rails-bootstrap-forms git (not old pluralize bootstrap_forms). Just add two lines
cat >> Gemfile << HERE_DOC
# adding bootstrap_form_for
gem 'bootstrap_form'
HERE_DOC
sed -i app/assets/stylesheets/application.css -e '1i\
/*\
*= require rails_bootstrap_forms\
*/'
# or sass
cat >> app/assets/stylesheets/application.sass << HERE_DOC
// gems
@import 'rails_bootstrap_forms'
HERE_DOC
and use your bootstrap_form_for
You can use horizontal
forms
with layout: :horizontal
(note that it won’t work for string layout:
'horizontal'
). You can add options label_col: 'col-sm-4', control_col:
'col-sm-8'
. Also you can override control_class
, wrapper_class
(if it is a
hash you can override any option).
If you want all controlls and submit button to be in one line, you can use
layout: :inline
(note that only symbols works, string does not layout:
'inline'
). For text_field maximum size use
<%= bootstrap_form_for @form, layout: :inline do |f|
<%= f.text_field :name, size: 2 %>
<% end %>
Use placeholders instead of labels
<%= f.text_field :email, label_as_placeholder: true %>
For Select2, you can resolve with to the current value (for ajax you need to
populate with prompt: 'Please select'
). I need to populate with label so I add
this helper
# app/form_builders/my_form_builder.rb
class MyFormBuilder < BootstrapForm::FormBuilder
def select(method, choices = nil, options = {}, html_options = {}, &block)
if options.delete :label_as_prompt
options[:prompt] = form_group_placeholder(options, method)
else
options[:prompt] ||= I18n.t('please_select')
end
super
end
end
you can make checkbox inline with button
<%= f.check_box :remember_me, inline: true %>
<%= f.submit t "sign_in" %>
You can change form-group wrapper class so to make two inputs inline you wrap
with form-inline
. If you need more customisation you can override wrapper
class
<div class='form-inline'>
<%= f.text_input :name, wrapper_class: 'form-group__with_select'
</div>
You can also use bootstrap row and cols or d-flex
<%= f.text_field :name %>
<div class='d-flex flex-row justify-content-between'>
<div>
<%= f.text_field :address %>
</div>
<div>
<%= f.text_field :city %>
</div>
</div>
You can use form to have horizontal layout, and some input group can be inline, so you can group input and select (note that is you have horizontal layout you can not use this since col-sm-2 and col-sm-10 will be added, look below for custom form builder).
<%# app/views/todos/_form.html.erb %>
<%= bootstrap_form_for @task, url: todos_path do |f| %>
<div class="form-inline">
<%= f.label :name %>
<div class="input-group input-group__with-select">
<%= f.text_field :name, input_group_class: 'input-group-under-group-with-select', skip_label: true %>
<%= f.select :id, 1..5, skip_label: true %>
</div>
</div>
<% end %>
# app/assets/stylesheets/application.scss
.input-group__with-select {
.input-group-under-group-with-select,.form-group {
position: initial;
display: initial;
border-collapse: initial;
}
.form-control {
width: 50%!important;
}
}
You can prepend or append strings or buttons
<%= f.text_field :price, append: '$' %>
<%= f.text_field :body, append: f.primary(t('send')) %>
Checkboxes or radio buttons should be inside a form-group
if you want to show
them indented (inside wrapper class) and to show label (control class) and help
text
<%= f.form_group label: { text: 'Admin', for: 'admin' }, help: 'This option enables admin' do %>
<%= f.check_box :admin, hide_label: true, id: 'admin' %>
<% end %>
To hide label instead of label: ''
you need to use hide_label: true
Static text can be displayed with
<%= f.static_control :email %>
<%= f.static_control label: 'Custom Static Control' do %>
Content here
<% end %>
You can use original rails form builder appending _without_bootstrap
<%= f.text_field_without_bootstrap :name %>
Form builder
You can write your own form builder that extends for example
rails-bootstrap-forms
But since bootstrap_form_for
(which is defined inside helper) calculate layout
class (:inline
or :horizontal
) we need to use same helper
(bootstrap_form_for ... builder: MyFormBuilder
instead of form_for ...
builder: MyFormBuilder
). I noticed huge chrome memory problems (memory chrome
is increasing when there is no form-horizontal
class).
To override some form elements you need to override bootstrap_form_for helper
# app/helpers/form_helper.rb
module FormHelper
include BootstrapForm::Helper
def bootstrap_form_for(object, options = {}, &block)
options.reverse_merge! builder: MyFormBuilder
super(object, options, &block)
end
def bootstrap_form_with(options = {}, &block)
options.reverse_merge! builder: MyFormBuilder
super(options, &block)
end
def options_for_select(container, attr = {})
# do not show Const.not_specified option
container = container.reject { |k, _| k.to_s.match Const.not_specified } unless attr[:show_not_specified]
super container, attr
end
end
Oneliner form is using button_to with: input label, target url, form class…
<%= button_to t('notify'), notify_device_path(device), class: 'btn btn-sm btn-secondary', title: t('send_notification_to_this_device'), form_class: 'd-inline' %>
You can change default col-sm-2
control col class
# config/initializers/bootstrap_form.rb
module BootstrapForm
class FormBuilder
def default_label_col
'col-sm-3'
end
def default_control_col
'col-sm-9'
end
end
end
Here is example of input with select base od example
# app/form_builders/my_form_builder.rb
class MyFormBuilder < BootstrapForm::FormBuilder
def my_text_field(method, options = {})
content_tag :div, class: "my-wrapper" do
super method, options
end
end
def text_field_with_select(method_for_text_input, options_for_text_input, method_for_select, choices, options_for_select = {}, html_options = {})
content_tag :div, class: "from-group form-group__with_select" do
form_group_builder method_for_text_input, options_for_text_input do
select_without_group = form_group_builder_without_group(method_for_select, options_for_select, html_options) do
select_without_bootstrap(method_for_select, choices, options_for_select, html_options)
end
text_field_without_bootstrap(method_for_text_input, options_for_text_input) +
select_without_group
end
end
end
# this will overwrite all f.submit form helpers. data-disable-with does not
# work well when responding with csv so there you should explicitly disable:
# <%= f.submit "Generate CSV", 'data-disable-with': nil %>
def submit(name, options = {})
options.reverse_merge! 'data-disable-with': "<i class='fa fa-spinner fa-spin'></i> #{name}"
hidden_field_tag(:commit, name) +
button(name, options)
end
def single_image_upload(method, options = {})
end
private
def form_group_builder_without_group(method, options, html_options = nil)
# copy from original form_group_builder
# bootstrap_form-2.5.2/lib/bootstrap_form/form_builder.rb
options.symbolize_keys!
html_options.symbolize_keys! if html_options
# Add control_class; allow it to be overridden by :control_class option
css_options = html_options || options
control_classes = css_options.delete(:control_class) { control_class }
css_options[:class] = [control_classes, css_options[:class]].compact.join(" ")
options = convert_form_tag_options(method, options) if acts_like_form_tag
wrapper_class = css_options.delete(:wrapper_class)
wrapper_options = css_options.delete(:wrapper)
help = options.delete(:help)
icon = options.delete(:icon)
label_col = options.delete(:label_col)
control_col = options.delete(:control_col)
layout = get_group_layout(options.delete(:layout))
form_group_options = {
id: options[:id],
help: help,
icon: icon,
label_col: label_col,
control_col: control_col,
layout: layout,
class: wrapper_class
}
if wrapper_options.is_a?(Hash)
form_group_options.merge!(wrapper_options)
end
unless options.delete(:skip_label)
if options[:label].is_a?(Hash)
label_text = options[:label].delete(:text)
label_class = options[:label].delete(:class)
options.delete(:label)
end
label_class ||= options.delete(:label_class)
label_class = hide_class if options.delete(:hide_label)
if options[:label].is_a?(String)
label_text ||= options.delete(:label)
end
form_group_options.merge!(label: {
text: label_text,
class: label_class,
skip_required: options.delete(:skip_required)
})
end
form_group_without_group(method, form_group_options) do
yield
end
end
def form_group_without_group(*args, &block)
options = args.extract_options!
name = args.first
options[:class] = ["form-group", options[:class]].compact.join(' ')
options[:class] << " #{error_class}" if has_error?(name)
options[:class] << " #{feedback_class}" if options[:icon]
control = capture(&block).to_s
control.concat(generate_help(name, options[:help]).to_s)
control.concat(generate_icon(options[:icon])) if options[:icon]
control
end
end
end
Data confirm modal
When rails use data-confirm='Are you sure?'
it opens default browser’s builtin
confirm()
. Instead of that, you can open bootstrap 3 or 4 modal with
https://github.com/ifad/data-confirm-modal
Navbar
navbar
is starting class whichdisplay: flex; flex-wrap: wrap; align-items: center; justify-content: space-between
(so if you have two childs likenavbar-brand
andnavbar-toggler
they will be on left and right side, butnavbar-collapse
hasflex-grow: 1; flex-basis: 100%
so that’s why it looks like it’s on left, alsonavbar-expand-lg
hasjustify-content: flex-start
).navbar-light bg-light
to add colors (it will change color of nav-links)navbar-collapse
contains all navbar. addnavbar-expand-lg
on navbar so on lgnavbar-toggler
dissapears,navbar-collapse
expands andnavbar-nav
change fromcolumn
toflex-direction: row
. Insidenavbar-collapse
besidenavbar-nav
you can also nest one morenavbar-nav ml-auto
if you want to pull some links to right.
Cards
<div class="card" style="width: 18rem;">
<img class="card-img-top" src=".../100px180/" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
<a href="#" class="btn btn-primary">Go somewhere</a>
</div>
</div>
Cards occupy full width, so you need to set width manually.
You can use card-group
or card-deck
(it has padding), or you can simply add
d-flex flex-wrap
to wrapped element.
card-body
is used for padding.
# app/assets/stylesheets/components/sizes.sass
.card--max-width
@include media-breakpoint-up(md)
// single card on sm and start with two on a md(minus two margins m-2)
max-width: map-get($grid-breakpoints, 'md') / 2 - to-px(2 * map-get($spacers, 2))
# app/views/cards/index.html
<div class='d-flex flex-wrap justify-content-center'>
<% @tasks.all.each do |task| %>
<div class='card m-2 card--max-width'>
<div class='card-body'>
To add buttons to card using list group, use flush to remove some borders and
render edge to edge, use btn
to add hover icon
<div class='card'>
<div class='list-group list-group-flush text-center'>
<%= button_tag class: 'list-group-item list-group-item-action btn' do %>
<i class="fa fa-pencil-alt" aria-hidden="true"></i>
<%= t('edit') %>
<% end %>
</div>
Login box
On responsive, instead of margin (margin is used with auto so it is
centered on bigger screens) you can use max-width: 90vw
or better is to wrap
inside container with padding: 0.5rem
.
Since I like to put a logo and text which is larger than box, I use two times
max with and mx-auto, one for wrapper (60rem) and one for white box (sm size).
# app/assets/stylesheets/common/sizes.sass
.login--wrapper-max-width
max-width: 60rem
.login--max-width
max-width: 30rem
# app/views/layouts/application.html.erb
<% if login_layout? %>
<body>
<div class='text-center'>
<%= link_to root_path do %>
<%= image_tag 'cable_crm_logo.png', class: 'login-logo' %>
<% end %>
<h2><%= login_title %></h2>
</div>
<div class='container'>
<div class='login--wrapper-max-width mx-auto'>
<div class="<%= 'login--max-width mx-auto bg-white shadow p-4' unless controller_name == 'companies' %>">
<%= yield %>
</div>
</div>
</div>
</body>
<% else %>
Sidebar
https://bootstrapious.com/p/bootstrap-sidebar#3-fixed-scrollable-sidebar-menu-with-a-content-overlay
# app/assets/stylesheets/components/sidebar.sass
$sidebar-width: 20rem
#sidebar
&.active
right: 0
min-width: $sidebar-width
max-width: $sidebar-width
height: 100vh
position: fixed
top: 0
right: -$sidebar-width
background: #7386D5
color: #fff
transition: right 0.3s
z-index: 9999
.sidebar__overlay
display: none
position: fixed
width: 100vw
height: 100vh
background: rgba(0, 0, 0, 0.7)
z-index: 998
opacity: 0
transition: all 0.5s ease-in-out
&.active
display: block
opacity: 1
.sidebar__dismiss
width: 35px
height: 35px
position: absolute
top: 10px
right: 10px
# app/views/layouts/_sidebar.html.erb
<nav id='sidebar'>
<div class='sidebar__dismiss' data-toggle-active='#sidebar,.sidebar__overlay'>
<i class="fa fa-times"></i>
</div>
<ul class='list-unstyled'>
<p>My App</p>
<li class='<%= 'active' if controller_name == 'tasks' %>'>
<%= link_to 'Past tasks', '#' %>
</li>
</ul>
</nav>
<div class='sidebar__overlay' data-toggle-active='#sidebar,.sidebar__overlay'></div>
Improvements
- create classes for text primary for list groups. There is only a color
variants
list-group-item-primary
but I do not see variant with white background and blue text https://github.com/twbs/bootstrap/blob/v4-dev/scss/_list-group.scss#L148 My fix is:// by defauls list-group-item-action.active background is white, but when we add // text-primary if overrides that, so we need to define again .list-group-item-action.active.text-primary color: #ffffff !important &:hover color: #ffffff !important
- to check if postcss autoprefixer was applied you need to create
<select class='custom-select'></select>
and inspect that element. When there is no autoprefixer than it will containappearance: none
, if there is autoprefixed than it will be-mox-appearance: none
or-webkit-appearance: none
- badge label
<span class="badge badge-primary">Primary</span>
- use with webpacker is simply adding few lines of stylesheets
https://github.com/bootstrap-ruby/bootstrap_form/issues/554
# app/javascript/stylesheets/application.scss: @import "~bootstrap/scss/bootstrap"; // https://github.com/bootstrap-ruby/bootstrap_form/issues/554 .rails-bootstrap-forms-date-select select, .rails-bootstrap-forms-time-select select, .rails-bootstrap-forms-datetime-select select { display: inline-block; width: auto; } .rails-bootstrap-forms-error-summary { margin-top: 10px; }