• when you want to have smaller input field type number (smaller in terms of width) you need to provide both min and max, like <input type="number" min="0" max="99">
  • to hide long text on div/dt width: 100px than you can:
    • long string overflow: hidden; text-overflow: ellipsis; To show on hover, focus or active (when selecting text) use this helper
      // <div class='long-string-three-dots'>long long</div>
      .long-string-three-dots {
      text-overflow: ellipsis;
      overflow: hidden;
      // white-space: nowrap;
      &:active, &:hover, &:focus {
        text-overflow: initial;
        overflow: auto;
      }
      }
      
    • long text can be in one line white-space: nowrap; no wrap means it will no go to the next line even for white space.
    • long strings can be shown on multiple lines with word-wrap: break-word this will break long string to multiple lines (for text white-space: normal)
  • if you have <small> position relative, and apply left -100px, it will still occupy the space where it was. It is better to use position: absolute
  • to move element to the right but keep inside parent element you need to mark parent as position: relative and than use position: absolute; right: 10px
  • align element at bottom use position relative/absolute pair, for parrent position: relative (does not have any effects) and for child: position: absolute;bottom: 10px;. This question explains why outer need to be relative.
  • use mouseenter instead mouseover (which will retrigger on inner elements).
  • use relative units instead of absolute http://www.w3schools.com/cssref/css_units.asp, for example header h1 { font-size: 20vh;}. vh is 1% of vertical heigh of view port (window size, not page size). For width you can use horizontal width for example width: 80vw;. You should use relative size rem (to the html el) or em (to the current font) since you might want to change font size on whole page, and you do not need to go to all nested components to update that. 1rem is default font size usually 16px, bootstrap was 14px now is also 16px.

  • you can not set the width of inline elements, so to set width of span you need to make it display:inline-block; width: 100px. Also if you have text than inline or inline-block element with block inside, it will behave differently
              inline-block
    some_text nested_block
    
    some_text inline
    nested_block
    
  • also top and bottom padding has no efect for label since it is an inline element link. You need to make the label a block level element for it to work.
  • space inside a element is important. for example <label>1</label><label> 2 </label><label> 3 </label> with label { background: blue;} this background will occupy only character and it will be disconnected from 1-2, but connected 2-3. This margin-like separation will also be presented if label { display: inline-block; }. It seems that space is important only with inline elements.
  • if you need to render divs horizontaly (float: left) you need parent to have width = number_of_items * (item_width+2*item_border_width) I calculate that in javascript

    <script>
      $(function() {
        $('.slots-preview').width($('.slots-preview-item').first().outerWidth() * <%= scheduler.number_of_free_slots.count %>);
      });
    </script>
    

    You can add scrollbar by wrapping it .outer { overflow-x: scroll } link

  • textarea (rails f.text_area) has constant size, so if you want bigger you can set rows="30" (and cols="150") or use autosize

  • when you use padding than child with width: 100% it is calculated based on parent content (parent border and padding is added). Solution is to use box-sizing: border-box in which calculated size will include border and padding https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing. This is usually included in bootstrap. Problem with padding arise when you use position: relative on parent and position: absolute on child https://stackoverflow.com/questions/17115344/absolute-positioning-ignoring-padding-of-parent Solution is to add relatively position div with no padding around absolutely position div. So when you are using padding and absolute position child, always add child relative wrapper with no padding. Another solution is to use left: 0; on absolutively child.

Examples

SCSS Sass

  • you can set default value of variable $my-var: 123 !default;. This has no effect if variable is already defined. In CSS you can define var with --main-color: black; and use with color: var(--main-color);. Var are usually decraler on pseudo class :root { --main-color: black; } so it is accessible everywhere, instead of local scope (since this is custom property, it is accessible only on matching selector and its descendants) which is used only for specific elements like BEM
  • https://responsivedesign.is/develop/getting-started-with-sass
  • you can select this using &

    .a:hover {
      background: blue;
    }
    // is the same as
    .a {
      &:hover {
        background: blue;
      }
    }
    
  • prefer mixins to @extend. You can pass parameter to mixin and set default value

    @mixin grid($my_var: true) {
      // code here
    }
    

Sass is shorter since it uses indent, and do not require semicolon. Atomatic convert scss to sass

sass-convert -F scss -T sass application_styles.css.scss application_styles.css.sass

Instead of scss

# scss
@mixin border-radius($radius) {
  border-radius: $radius;
}

.box {
  @include border-radius(10px);
}

# sass
=border-radius($radius)
  border-radius: $radius

.box
  +border-radius(10px)

Head meta tags

  • here is a list of used tags HEAD
  • chrome 39 for android use different color for toolbar, just add <meta name="theme-color" content="#db5945">

Css helper classes

// add some space below
.m-b-10 {
  margin-bottom: 10px;
}

// similar to pull-right just without float
.text-align-right {
  text-align: right;
}

// hide  submit buttons, since android has problems when element is not visible
.hide-to-up {
  position:absolute;
  top: -1000px;
}
// Here is example to show hide buttons that are not allowed for first or last
//
// <ol>
//   <!-- iterate over li -->
//   <li  class="hide-first-child hide-last-child">
//     <a class="hide-first-target"><i class="fa fa-arrow-up"></li></a>
//     <a class="hide-last-target"><i class="fa fa-arrow-down"></li></a>
//   </li>
// </ol>

.hide-first-child:first-child .hide-first-target {
  display: none;
}

.hide-last-child:last-child .hide-last-target {
  display: none;
}

// if you need to nest two show hide (you have another ul inside li)
.hide-first-child:first-child {
  .hide-first-target {
    display: none;
  }
  .hide-first-child {
    .hide-first-target {
      display: initial;
    }
    &:first-child {
      .hide-first-target {
        display: none;
      }
    }
  }
}

.hide-last-child:last-child {
  .hide-last-target {
    display: none;
  }
  .hide-last-child {
    .hide-last-target {
      display: initial;
    }
    &:last-child {
      .hide-last-target {
        display: none;
      }
    }
  }
}
// show on hover
//
//  <li class="show-on-hover">
//    Text<a href="" class="show-on-hover-target">X</a>
//  </li>
.show-on-hover-target {
  visibility: hidden;
}
.show-on-hover:hover {
  .show-on-hover-target {
    visibility: visible;
  }
}

// add class show to stay visible when not hovering, bootstrap dropdown does dat
.show-on-hover-target.show {
  visibility: visible;
}
// expand on hover
// used on index tables when some data is too long to be always shown
//
// <td class="expand-on-hover"><%= account.uuid %></td>

.expand-on-hover {
  width: 20px;
  height: 10px;
  overflow: hidden;
  float: left;
}
.expand-on-hover:hover {
  width: inherit;
}

To expand block on click use input checkbox https://www.sitepoint.com/pure-css-off-screen-navigation-menu/

Note that input is before label, which is before target

// toggle active without javascript
// <input type="checkbox" id="toggle-active" class="toggle-active" />
// <label for="toggle-active"><%= t('add') %></label>
// <div class="toggle-active-target hide-not-important">
// </div>
// https://www.sitepoint.com/pure-css-off-screen-navigation-menu/
.toggle-active {
  position: absolute;
  clip: rect(0, 0, 0, 0);

  &:checked ~ .toggle-active-target {
    display: initial;
  }
}
label[for="toggle-active"] {
  cursor: pointer;
}

To show active on click in pure css use li:hover { color: blue }

Design

  • when you are asking user to select items from long lists, you should have Next before and after the list so user does not need to scroll
  • be proactive with messages, when user needs to type password again (for example signin with fb and confirm) than write Excellent, we need just...
  • when hover on footer link, other link in same block should be opacity demo

    ul:hover li:hover {
      opacity: 1;
    }
    ul:hover li {
      opacity: 0.4;
    }
    

Image

Swap images and zoom on hower https://www.filamentgroup.com/lab/sizes-swap/

Flex

https://css-tricks.com/snippets/css/a-guide-to-flexbox/#flexbox-background https://medium.com/@js_tut/flexbox-the-animated-tutorial-8075cbe4c1b2

Parent element if flex container, and children as flex items. flex-direction determines main axis on which items will be laid out from main-start (flex-start) to main-end (flex-end), that is total main-size. Perpendicular to the main axis is cross axis with its cross-start cross-end and cross-size.

on container we can have:

  • display: flex (synonim is inline-flex)
  • flex-direction: row | row-reverse | column | column-reverse
  • flex-wrap: nowrap | wrap | wrap-reverse default is no wrap so in single line, wrap means that it is allowed to go onto multiple lines. This two properites can be shorhanded in one flex-flow: row nowrap
  • justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly alignment when items are inflexible. space around means that all items have same space around (before first there is no items so that’s why it is single space) if you need exactly same space from start to first and first to second, use space-evenly.
  • align-items: flex-start | flex-end | center | stretch | baseline behavior along CROSS AXIS on current line. stretch is from cross-start to cross-end still respect min-width/max-width. similar to justify-content but for cross axis
  • align-content: flex-start | flex-end | center | stretch | space-between | space-around behavior of LINES when there is extra space in cross-axis (no effect is single line) similar to justify-content for main axis, but for lines.

on items https://www.w3.org/TR/css-flexbox-1/#flexibility

  • flex-grow: 0 ability to grow as proportion. If one has 2 and all others have 1, first will be twice bigger
  • flex-shrink: 1
  • flex-basis: 20% | auto default size before remaining space is distributed (you this if you want max-size: 20%) This three items have shorthand flex: 0 1 auto. So use this if you want items to use space between (on container clear justify-content) flex: auto is eq to flex: 1 1 auto bigger item will take bigger space, auto means that if item can use space it will use space. flex: 1 is eq to flex: 1 1 0 all items same width (flex-basis 0 so their content is not taken into consideration)
  • align-self: flex-start | flex-end | center | stretch | baseline override align-items for specific item, on cross axis
  • order: 0

  • justify-items property defines the default justify-self for all items for a display: grid.

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Typical_Use_Cases_of_Flexbox You can use margin-left: auto to separate group of items since auto margin will took as much space as it can. So you can align first three on left and last two on right by adding .push on firt right item.

.box {
  display: flex;
}
.push {
    margin-left: auto;
}

<div class="box">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div class="push">Four</div>
  <div>Five</div>
</div>

Om mobile you probably want all buttons to take all space so use flex: auto or flex: 1 if you want same size buttons.

https://hacks.mozilla.org/2018/01/new-flexbox-guides-on-mdn/ https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox

Flexbox

Used in layout in one dimension at a time (either row or column).

CSS Grid https://mozilladevelopers.github.io/playground/css-grid

CSS box alignment

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Alignment older alignment methoods were:

  • align text using text-align In bootstra for text you can use text-center text-right helper classes for to align text right.
  • center blocks using auto margin for block elemenent with margin: auto (bootstrap center-block helper) does not have effect unless the element has the width (because it can not calculate margins)
  • in inline-block elements use vertical-align: baseline for image to be on same bootom as other elements
  • to make vertical align you need parent to be position: relative, and target to be position:absolute; top: 50%; margin-top: -1rem; (if you show text 1rem).

There are two axis: inline (main) and block (cros) axis. When aligning items on inline axis we use properties that starts with justify- and when aligning items on block axis we use align- (items, self, content). With flex-direction: row than main axis is block, and cross is inline. Three types of alignment:

  • positional alignment for -self and -content specify position of subject with relation to container: center, start, end, self-start, self-end, flex-start, flex-end, left, right.
  • baseline alignment for -self and -content specify relationship amount baselines of multiple subjects: baseline, first baseline, last baseline
  • distributed alignment for -content specify what happens to space after subject have been displayed: strech, space-between, space-around, space-evenly

Table

Table has two layouts

  • table-layout: auto dependends on widest unbreakable content in the cells
  • fixed faster since browser does not need full content

Rotate header link

<th class="rotate"><div><span>Column header 1</span></div></th>
th.rotate {
  /* Something you can count on */
  height: 140px;
  white-space: nowrap;
}

th.rotate > div {
  transform:
    /* Magic Numbers */
    translate(25px, 51px)
    /* 45 is really 360 - 45 */
    rotate(315deg);
  width: 30px;
}
th.rotate > div > span {
  border-bottom: 1px solid #ccc;
  padding: 5px 10px;
}

jQuery

some tips

  • jquery selectors
    • $('thead th[data-searchable!="false"]') select all th that do not have data-searchable or have it but different than false
  • if jQuery finder returns n,fn.init that means it did not find DOM elemenent link

when found an element based on the selector criteria it returns the matched elements; when the criteria does not match anything it returns the prototype object of the function.

With jquery you can create elements $('<div>'). If you want additional properties you can pass as additional params var $div = $('<div>', { id: 'foo', class: 'my_class'}). You can join elements with: append, prepend, after and before. Here you can use jquery objects or plain html: $('#box').append($div).append('<div id="foo"></div>').

Tips

  • submit button outside of a form is possible

    <form id="myform" method="get" action="something.php">
    <input type="text" name="name" />
    </form>
    
    <input type="submit" form="myform" />
    
  • note that if you have multiple submit inputs and one text input field, when you press Enter, only first submit button will be used (so commit value will be it’s value). you can disable submit on enter with

    $('#notification-form').on('keyup keypress', function(e) {
      var keyCode = e.keyCode || e.which;
      if (keyCode === 13) {
        e.preventDefault();
        return false;
      }
    });
    

    I made helper data function which will also click. put on document ready or turbolinks load.

    # app/assets/javascripts/turbolinks_loads.coffee
    # f.text_field :email, 'data-prevent-submit-on-enter': '#email-continue'
    $(document).on 'turbolinks:load', ->
      $('[data-prevent-submit-on-enter]').on 'keyup keypress', (e) ->
        keyCode = e.keyCode || e.which
        if keyCode == 13
          e.preventDefault()
          $($(this).data().preventSubmit).click() if $(this).data().preventSubmitOnEnter != true
    
  • <input readonly="readonly"> is better to use than <input disabled="disabled"> since it can receive focus, included in tabbing navigation and values are successfully posted (disabled input is not send to server).
  • if you need two css files, than write two <link rel="stylesheet" type="text/css" href="1.css" /> . Do not use @import url("2.css") in 1.css since it will prevent downloading files in parallel (2.css is downloaded only after 1.css). Only user of @import is when you provide media queries as parameter and load only for specific screen. Note that sass preprocessor scss @import will include inline the code.
  • if option select is required, we usually prompt user with one more option “Please select”, but it is bad to allow user to pick that option “Please select”. You can disable option, and you should force selected on it if other option is not selected demo

      <select onchange="this.form.submit()">
        <option selected="selected" disabled="true">--Please Select --</option>
        <option value="volvo">Volvo</option>
        <option value="saab">Saab</option>
      </select>
    

    In rails, you can use with select_tag:

      <%= select_tag "job[job_type_id]",("<option #{ "selected='selected'".html_safe unless fjob.object.job_type_id } disabled='disabled'>Job Type</option>".html_safe+ options_from_collection_for_select(JobType.active.all, :id, :name,{selected: fjob.object.job_type_id})), { class: "e1" } %>
    

    or with f.collection_select

      <%= f.collection_select :user_id, User.all.unshift(User.new id: 0, name:
      "Please Select User"), :id, :name), {}  %>
    

    or f.select

      <%= f.select :shopify_custom_collection_id, [['Please select collection',0]] + @shopify_custom_collections.map { |shopify_custom_collection| [shopify_custom_collection.title, shopify_custom_collection.id] }, disabled: 0, selected: 0 %>
    
  • if you want to filet group select based on first option than use something like

https://stackoverflow.com/questions/32405077/show-second-dropdown-options-based-on-first-dropdown-selection-jquery

  • <a href="javascript:void(0)"> is required when you use onclick= and do not want page to reload
  • input type="checkbox" onchange="perform(this.checked) you can get value with input.checked. with jquery $(input).is(':checked')
  • in css file you can include comment for source maps, for example /*# sourceMappingURL=bootstrap-datepicker3.css.map */
  • plain <input> has default with (probably 157px), but if you want to set size, use style="width: 100%"
  • if you want background image to be blured, you can use overlay with opacity position absolute that cover whole area. Your element should be position relative and defined after cover to stand out of that cover. https://css-tricks.com/snippets/css/transparent-background-images/
<body>
  <div class="gradient"></div>
  <div class="my-stuff"></div>
</div>
.my-stuff {
  position: relative;
}
.gradient {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  opacity: .7;
  background-color: #52d3aa;
  // use image
  background-image: asset-url("cityscape.png")

  // or gradient
  -webkit-backface-visibility: hidden;
  background-image: -webkit-gradient(linear, 0% 0%, 100% 100%, color-stop(0, #3f95ea), color-stop(1, #52d3aa));
  /* Android 2.3 */
  background-image: -webkit-repeating-linear-gradient(top left, #3f95ea 0%, #52d3aa 100%);
  /* IE10+ */
  background-image: repeating-linear-gradient(to bottom right, #3f95ea 0%, #52d3aa 100%);
  background-image: -ms-repeating-linear-gradient(top left, #3f95ea 0%, #52d3aa 100%);
}
  • for phone you need to use <a href="tel:123123">+123-123</a> (rails <%= link_to "+123-123", "tel:123123" %>)
  • for mail <a href="mailto:asd@asdasd">asd@asd.asd</a> (rails <%= mail_to "asd@asd.asd", "asd@asd.asd" %>)
  • for event listeners always use e.currentTarget since it is element on which listener was bound. Do not use e.target since it could be child element. Example $('[data-user-preferences]').click(function(e) { e.currentTarget.dataset.userPreferences })
  • if you need to click on the underlying elements under other, you can use https://stackoverflow.com/questions/3680429/click-through-a-div-to-underlying-elements
    pointer-events: none
    
  • accordion is native in html (you do not need bootstrap accordion collapse in javascript)

    <details>
      <summary>Hi</summary>
      Bye
    </details>
    
    <details>
      <summary>How do I get to New Orleans?</summary>
      Use Google Maps.
    </details>
    
    details {
      margin: 1rem;
    }
    summary {
      font-weight: bold;
    }
    

    You can style different states of defails (details[open] and details:not[open]) https://codepen.io/jh3y/pen/mLaXRe

  • text input can have focus on page load with <input autofocus> (f.text_field :name, autofocus: true in rails)

  • prevent auto completing text inputs can be prevented with `<%= text_field_tag
  • :other_reason, nil, autocomplete: ‘off’ %>` (note is should be ‘off’ not ‘false’