Feedback Stay at home and get up to 40% off with STAYATHOME coupon code | 0d 0h 0m 0s left

Style & Theme

#Binding CSS Classes

To add CSS classes to an element simply add class property to it's schema and you will have that on the outermost container the element template has.

public function schema() {
  return [
    'name' => 'text',
    'label' => 'Name',
    'class' => 'name-element'
  ];
}

Why are we using the term outermost? Because each theme provides their own layouts and templates for elements while all of them have in common that the class defined by the user in schema must be placed at the outermost container the element has.

Let's see a very simplified example to illustrate this:

// TextElement's template

<template>
  <div class="element-container" :class="schema.class">
    <div class="element-inner">
      <div class="label-container">
        <label :for="name">{{ label }}</label>
      </div>
      <div class="field-container">
        <input v-model="model" type="text" />
      </div>
    </div>
  </div>
</template>

You can see that this is a simplified TextElement template, where the element-container receives the class defined in schema.

While this is a simple and easy solution if we want to add a class only to the element container, but what if we want to specify a class for let's say the label-container or field-container? See how we can do that.

#Additional Classes

Themes, as you will see in the next section, contain a predefined list of classes that components use. In the previous example we've used static classes within the component's template, but in fact they are dynamically assigned. So that's how are template from above actually looks like:

// TextElement's template

<template>
  <div :class="[theme.classes.elementContainer, schema.class]">
    <div :class="theme.classes.elementInner">
      <div :class="theme.classes.labelContainer">
        <label :for="name">{{ label }}</label>
      </div>
      <div :class="theme.classes.fieldContainer">
        <input v-model="model" type="text" />
      </div>
    </div>
  </div>
</template>

Using this method you can override template classes on the flight, using the classes option of an element:

public function schema() {
  return [
    'name' => 'text',
    'label' => 'Name',
    'class' => 'name-element'
    'classes' => [
      'elementContainer' => 'name-element-container',
      'fieldContainer' => 'name-element-field'
    ]
  ];
}

So now instead of the theme's default elementContainer and fieldContainer CSS class the ones defined for the element will be used.

#Using Themes

The default theme can be set globally in configiration:

/**
* Default theme.
* 
* Learn more at: /style-and-theme#using-themes
*/
theme: 'default',

It can be also set on a form level, if you want to use a different one for specific forms:

<?php

namespace App\Forms;

class Form extends \Laraform
{
  public $theme = 'my-theme';
}

To learn how you can create a custom theme, checkout Creating Theme chapter.

#Theme File

Each theme has an index.js called the theme file in it's root directory which exports an object, which is called the theme object:

// ./path/to/theme/index.js

export default {
  classes: {},    // CSS class names the components use
  elements: {},   // element components
  components: {}, // components of the form
  layouts: {},    // definition of the framework's layouts
  grid: {}       // definition of the framework's grid system
}

As you can see it has several properties, so let's go through each of them.

'classes' Property

The classes property contains a list of CSS classes that components use. This means that the CSS class names of components are not typed in their actual templates but referenced from the theme's classes object. Let's see what we mean by that. Here we have a theme file with several class names defined:

// ./path/to/theme/index.js

export default {
  classes: {
    elementContainer: 'element-container',
    elementInner: 'element-inner',
    labelContainer: 'label-container',
    fieldContainer: 'field-container',
  },
  // ...
}

Now as each component in Laraform have access to an injected property called theme, this is how a simplified TextElement template would look like:

// TextElement's template

<template>
  <div :class="[theme.classes.elementContainer]">
    <div :class="theme.classes.elementInner">
      <div :class="theme.classes.labelContainer">
        <label :for="name">{{ label }}</label>
      </div>
      <div :class="theme.classes.fieldContainer">
        <input v-model="model" type="text" />
      </div>
    </div>
  </div>
</template>

As you can see, CSS classes are referenced from the theme file via injected theme property.

'elements' Property

Each component within Laraform consist of two different files. The first contains the <script> part of a single file component and placed in Laraform's /components/ folder, while the second is responsible for having the <template> and defined by the theme. Let's see how does that look like:

// laraform/src

.
├── index.js
├── components // core components (scripts only)
|   ├── elements
|   |   ├── HiddenElement.js
|   |   ├── TextElement.js
|   |   └── ...
|   ├── FormButtons.js
|   ├── FormTabs.js
|   └── ...
├── themes
|   ├── bs4
|   |   ├── components // component views (templates only)
|   |   |   ├── elements
|   |   |   |   ├── HiddenElement.vue
|   |   |   |   ├── TextElement.vue
|   |   |   |   └── ...
|   |   |   ├── FormButtons.vue
|   |   |   ├── FormTabs.vue
|   |   |   └── ...
|   └── index.js
└── ...

As you can see within /components/ directory there are the core files which have the <script> parts and then there are views in /themes/bs4/components/ which contains the <template> unique for the theme.

This way business logic and views can be completely separated for each component and different themes can define different views for the same components.

The elements property of the theme file contains the list of theme element views provided by the theme:

// ./path/to/theme/index.js

import HiddenElement from './components/elements/HiddenElement.vue'
import TextElement from './components/elements/TextElement.vue'

export default {
  // ...
  elements: {
    HiddenElement,
    TextElement,
    // ...
  },
  // ...
}

'components' Property

Just like elements, other components also have their views defined uniquely by the theme as you've seen from the previous file structure.

The components property is to register all the other components which are not elements:

// ./path/to/theme/index.js

import FormButtons from './components/FormButtons.vue'
import FormTabs from './components/FormTabs.vue'

export default {
  // ...
  components: {
    FormButtons,
    FormTabs,
    // ...
  },
  // ...
}

'layouts' Property

A theme might have different form layouts, like Bootstrap have inline or horizontal. Different layout identifiers and their class names can be defined here, which later can be used by the form's layout property:

// ./path/to/theme/index.js

export default {
  // ...
  layouts: {
    inline: 'form-inline',
    horizontal: 'form-horizontal'
  },
  // ...
}

'grid' Property

If the CSS framework the theme is using a grid system then it's variables are defined here:

// ./path/to/theme/index.js

export default {
  // ...
  grid: {
    // Maximum number of columns.
    // Leave blank if columns are not
    // specified by numbers.
    columns: 12,

    // List of available breakpoints.
    breakpoints: ['xl', 'lg', 'md', 'sm', 'xs'],

    // Default breakpoint which will be used
    // if the user does not specify breakpoints
    // for column sizes.
    defaultBreakpoint: 'xs',

    // Class name template for columns;
    // `:` represents a variable.
    column: 'col-:breakpoint-:size',
  }
  // ...
}

#Theme Styles

The CSS styles of a theme is defined within it's theme.scss, called the theme style. This file is usually using variables that the CSS framework the theme is meant for uses, like $primary in case of Bootstrap. Therefore the theme.scss must be included in you app's .scss file where you include the CSS framework and has acccess to the variables.

For example:

// app.scss

// Fonts
@import url('https://fonts.googleapis.com/css?family=Nunito');

// Variables
@import 'variables';

// Bootstrap
@import '~bootstrap/scss/bootstrap';

// Laraform
@import '@laraform/laraform/src/themes/bs4/scss/theme'

Theme Variables

Each theme uses variables used across it's styles. Here's the list of these:

//== Genaral
//
//## Font sizes, colors, backgrounds and more.

$lf-primary-color: #24ACF8 !default;
$lf-danger-color: #bf5329 !default;
$lf-black-color: #000000 !default;
$lf-disabled-color: #9BB2BF !default;

$lf-text-color: #333333 !default;
$lf-font-size: 14px !default;
$lf-line-height: 1.6 !default;

$lf-gutter: 30px !default;
$lf-padding-base-horizontal: 12px !default;
$lf-padding-base-vertical: 6px !default;
$lf-form-group-margin-bottom: 15px !default;
$lf-border-radius: 4px !default;

$lf-passive-background: #d6e4ec !default;
$lf-passive-background-lighter: #e9eef1 !default;

$lf-input-font-size: 14px !default;
$lf-input-color: #555555 !default;
$lf-input-placeholder-color: #999999 !default;
$lf-input-bg: #ffffff !default;
$lf-input-bg-disabled: #eeeeee !default;
$lf-input-border: #cccccc !default;
$lf-input-border-focus: #66afe9 !default;
$lf-input-border-radius: $lf-border-radius !default;
$lf-input-height: 36px !default;

$lf-button-color: #636b6f !default;

$lf-cursor-disabled: not-allowed !default;

//== Date, datetime calendar
//
//## Width, radius, height

$lf-calendar-width: 307.875px !default;
$lf-calendar-date-radius: 50% !default;
$lf-calendar-date-height: 39px !default;

//== Uploader
//
//## Drag n drop, previews, icons

//** Drag 'n drop

$lf-dnd-background: #fafafa !default;
$lf-dnd-padding: 30px 30px !default;

$lf-dnd-border: 1px dashed #e7e7e7 !default;
$lf-dnd-border-hover: 1px dashed $lf-primary-color !default;
$lf-dnd-border-over: 2px dashed $lf-primary-color !default;
$lf-dnd-border-radius: 6px !default;

$lf-dnd-font-size: $lf-font-size !default;
$lf-dnd-font-size-title: $lf-font-size !default;
$lf-dnd-text-color: $lf-text-color !default;
$lf-dnd-text-color-title: $lf-text-color !default;

$lf-dnd-icon-color: #{str-replace(#{$lf-primary-color}, '#', '%23')} !default;

//** Preview

$lf-preview-margin-top: 15px !default;
$lf-preview-gallery-margin-right: 10px !default;

$lf-preview-ghost-background: #f1f1f1 !default;
$lf-preview-ghost-border-radius: $lf-border-radius !default;

$lf-preview-image-background: #fafafa !default;

$lf-preview-list-image-width: 64px !default;
$lf-preview-list-image-height: 64px !default;
$lf-preview-list-border: 1px solid #cccccc !default;
$lf-preview-list-border-radius: 5px !default;
$lf-preview-list-padding: 12px 12px !default;

$lf-preview-gallery-image-width: 80px !default;
$lf-preview-gallery-image-height: 80px !default;
$lf-preview-gallery-border: 1px solid #cccccc !default;
$lf-preview-gallery-border-radius: 5px !default;
$lf-preview-gallery-padding: 8px !default;
$lf-preview-gallery-width: 98px !default;

$lf-preview-avatar-silhouette-color: '%23CBE3F5' !default;
$lf-preview-avatar-placeholder-background-color: #EEF8FF !default;

//** Icons

$lf-file-remove-icon-color: #{str-replace(#{$lf-primary-color}, '#', '%23')} !default;
$lf-file-remove-icon-background-color: transparent !default;
$lf-file-remove-icon-background-color-hover: lighten($lf-primary-color, 40%) !default;
$lf-file-remove-icon-border-radius: 3px !default;

$lf-list-image-remove-icon-color: #{str-replace(#{$lf-input-color}, '#', '%23')} !default;
$lf-list-image-remove-icon-background-color: transparent !default;
$lf-list-image-remove-icon-background-color-hover: #f1f1f1 !default;
$lf-list-image-remove-icon-border-radius: 3px !default;

$lf-gallery-image-remove-icon-color: '%23ffffff' !default;
$lf-gallery-image-remove-icon-background-color: rgba(0,0,0,0.45) !default;
$lf-gallery-image-remove-icon-background-color-hover: rgba(0,0,0,0.7) !default;
$lf-gallery-image-remove-icon-border-radius: 0 4px 0 3px !default;

$lf-avatar-image-remove-icon-color: '%23ffffff' !default;
$lf-avatar-image-remove-icon-background-color: rgba(0,0,0,0.45) !default;
$lf-avatar-image-remove-icon-background-color-hover: rgba(0,0,0,0.7) !default;
$lf-avatar-image-remove-icon-border-radius: 4px !default;

$lf-upload-icon-color: #{str-replace(#{$lf-button-color}, '#', '%23')} !default;
$lf-clip-icon-color: #{str-replace(#{$lf-black-color}, '#', '%23')} !default;

//== Wizard
//
//## Padding, margins, backgrounds

$lf-wizard-margin: 0 0 30px 0 !default;
$lf-wizard-padding: 30px 0 !default;
$lf-wizard-border-bottom: 1px solid #e7e7e7 !default;

$lf-wizard-active-step-circle-background: #ffffff !default;

Each theme has these variables overwritten by it's own values, often using CSS framework based values, for example:

// ./path/to/bs4/scss/theme.scss

//== Genaral
//
//## Font sizes, colors, backgrounds and more.

$lf-primary-color: $primary !default;

You can override these variables at your project's .scss file:

// app.scss

// Fonts
@import url('https://fonts.googleapis.com/css?family=Nunito');

// Variables
@import 'variables';

// Bootstrap
@import '~bootstrap/scss/bootstrap';

// Laraform
@import '@laraform/laraform/src/themes/bs4/scss/theme'

// Overriding Laraform Bootstrap 4 theme variables
$lf-primary-color: #00aaff;

#Available Themes

Default

If you are not using a supported CSS framework you might want to go with our default theme, which does not have any dependency.

You can reach the theme here:

  • @laraform/laraform/src/themes/default/index.js
  • @laraform/laraform/src/themes/default/scss/theme.scss

For Community edition it's here:

  • ~laraform/src/themes/default/index.js
  • ~laraform/src/themes/default/scss/theme.scss

Bootstrap 3

If you are using Bootstrap 3, you can use Laraform's default bs3 theme to render your form compatible with the framework.

You can reach the theme here:

  • @laraform/laraform/src/themes/bs3/index.js
  • @laraform/laraform/src/themes/bs3/scss/theme.scss

For Community edition it's here:

  • ~laraform/src/themes/bs3/index.js
  • ~laraform/src/themes/bs3/scss/theme.scss

Bootstrap 4

If you are using Bootstrap 4, you can use Laraform's default bs4 theme to render your form compatible with the framework.

You can reach the theme here:

  • @laraform/laraform/src/themes/bs4/index.js
  • @laraform/laraform/src/themes/bs4/scss/theme.scss

For Community edition it's here:

  • ~laraform/src/themes/bs4/index.js
  • ~laraform/src/themes/bs4/scss/theme.scss