Roll Your Own PDO PHP Class
Roll Your Own PDO PHP Class
Roll Your Own PDO PHP Class
Last week I introduced PDO, a database abstraction layer that you can use in your applications to allow
for future flexibility in your database choice and protect you from SQL Injection.
Whilst the class we looked at is great for getting started with PDO quickly, it does have some
restrictions if you want to do more complicated things than simple selects, inserts, updates and deletes.
I think it is also far more beneficial to know exactly what is going on under the hood of your code. By
knowing exactly how something works you will gain a much deeper sense of understanding and you
will be able to troubleshoot and advance your code when the time comes.
So if you haven’t read last week’s post, go back and read that as an introduction to PDO, Prevent PHP
SQL Injection with PDO Prepared Statements.
<?php
class Database
{
}
Here we are simply defining a new class called Database.
Now in the tutorial.php file we need to include the class. Copy and paste the following line to include the
database class in your tutorial file.
// Define configuration
define("DB_HOST", "localhost");
define("DB_USER", "username");
define("DB_PASS", "password");
define("DB_NAME", "database");
Back in database.class.php, we need to set up the variables in the class.
// Instantiate database.
$database = new Database();
Hopefully you understand all of the above as there is nothing specifically PDO related so far.
Construct
The first method we will look at is the construct method.
public function __construct()
{
}
When a class has a construct method, it is automatically called on all newly-created objects. This
enables you to set up any initialisation you might need on the new object before it is used.
When using PDO, you need to set the database connection method because PDO can be used with many
different types of database. Each different database has a slightly different connection string. To set a
particular database connection type, we just set the specific string.
// Set DSN
$dsn = ‘mysql:host=’ . $this->host . ‘;dbname=’ . $this->dbname;
In this example I’m setting the DSN to MySQL and I’m using the host and the database name we defined
earlier.
If you know you are going to be using MySQL for the foreseeable future, this is probably going to be fine.
However, it does take away some of the flexibility and reusability of PDO by hardcoding the connection
into a string like this. To make this more flexible and resizable you would use Dependency Injection. I
think Dependency Injection deserves it’s own tutorial, so I’ll leave that for another day. Just be aware
that you could make your construct a lot more future proof.
Options
When connecting to the database we can set a couple of different attributes. To set these options on
connection, we simply include them as an array.
// Set options
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
PDO::ATTR_PERSISTENT
This option sets the connection type to the database to be persistent. Persistent database connections
can increase performance by checking to see if there is already an established connection to the
database.
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
PDO can use exceptions to handle errors. Using ERRMODE_EXCEPTION will throw an exception if an
error occurs. This then allows you to handle the error gracefully.
To read more about PHP exceptions, take a look at The ins and outs of PHP exceptions.
Handling exceptions in PHP deserves it’s own tutorial and is out of the scope of this tutorial. I’ll write a
tutorial for handling exceptions in the coming weeks.
Try/Catch
Next we use a try/catch block to attempt to make a connection, or handle any exceptions if an error
occurs.
Declare a new variables at the top of your class for the Database Handler and any errors.
private $dbh;
private $error;
Back in the construct method we attempt a new PDO instance.
try {
$this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
}
Next we catch any errors that might occur.
class Database{
private $host = DB_HOST;
private $user = DB_USER;
private $pass = DB_PASS;
private $dbname = DB_NAME;
private $dbh;
private $error;
public function __construct(){
// Set DSN
$dsn = ‘mysql:host=’ . $this->host . ‘;dbname=’ . $this->dbname;
// Set options
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
// Create a new PDO instanace
try{
$this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
}
// Catch any errors
catch(PDOException $e){
$this->error = $e->getMessage();
}
}
}
Query
The next method we will be creating is the query method.
The query method introduces the $stmt variable to hold the statement.
private $stmt;
Prepare
The query method also introduces the PDO::prepare function.
The prepare function allows you to bind values into your SQL statements. This is important because it
takes away the threat of SQL Injection because you are no longer having to manually include the
parameters into the query string.
Using the prepare function will also improve performance when running the same query with different
parameters multiple times.
Copy and paste the following method into your class:
}
Param is the placeholder value that we will be using in our SQL statement, example :name.
Value is the actual value that we want to bind to the placeholder, example “John Smith”.
Type is the datatype of the parameter, example string. Next we use a switch statement to set the
datatype of the parameter:
if (is_null($type))
{
switch (true)
{
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}
Finally we run bindValue.
$this->stmt->bindValue($param, $value, $type);
The final bind method is:
public function bind($param, $value, $type = null)
{
if (is_null($type))
{
switch (true)
{
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}
$this->stmt->bindValue($param, $value, $type);
}
Execute
The next method we will be look at is the PDOStatement::execute. The execute method executes the
prepared statement.
To begin a transaction:
public function beginTransaction(){
return $this->dbh->beginTransaction();
}
To end a transaction and commit your changes:
$database->bind(‘:fname’, ‘John’);
$database->bind(‘:lname’, ‘Smith’);
$database->bind(‘:age’, ’24’);
$database->bind(‘:gender’, ‘male’);
And finally we run execute the statement.
$database->execute();
Before running the file, echo out the lastInsertId function so you will know that the query successfully
ran when viewed in the browser.
echo $database->lastInsertId();
Insert multiple records using a Transaction
The next test we will try is to insert multiple records using a Transaction so that we don’t have to repeat
the query.
$database->bind(‘:fname’, ‘Jenny’);
$database->bind(‘:lname’, ‘Smith’);
$database->bind(‘:age’, ’23’);
$database->bind(‘:gender’, ‘female’);
And then we execute the statement.
$database->execute();
Next we bind the second set of data.
$database->bind(‘:fname’, ‘Jilly’);
$database->bind(‘:lname’, ‘Smith’);
$database->bind(‘:age’, ’25’);
$database->bind(‘:gender’, ‘female’);
And run the execute method again.
$database->execute();
Next we echo out the lastInsertId again.
echo $database->lastInsertId();
And finally we end the transaction
$database->endTransaction();
Select a single row
The next thing we will do is to select a single record.
$database->query(‘SELECT FName, LName, Age, Gender FROM mytable WHERE FName = :fname’);
Next we bind the data to the placeholder.
$database->bind(‘:fname’, ‘Jenny’);
Next we run the single method and save it into the variable $row.
$row = $database->single();
Finally, we print the returned record to the screen.
echo "<pre>";
print_r($row);
echo "</pre>";
Select multiple rows
The final thing we will do is to run a query and return multiple rows.
$database->query(‘SELECT FName, LName, Age, Gender FROM mytable WHERE LName = :lname’);
Bind the data.
$database->bind(‘:lname’, ‘Smith’);
Run the resultSet method and save it into the $rows variable.
$rows = $database->resultset();
Print the return records to the screen.
echo "<pre>";
print_r($rows);
echo "</pre>";
And finally display the number of records returned.
echo $database->rowCount();
Conclusion
And there you have it, your first rolled PDO database abstraction class. Hopefully this tutorial has
introduced the main aspects of PDO and how it actually works. I think actually creating something like
this is far more beneficial than using someone else’s library because you need to fully understand how
all of this works, even if it takes longer in the long run.
I’ve missed out, or brushed over a number of important areas throughout this tutorial to try and keep it
on topic. If you are interested in learning more about these related areas, subscribe to our RSS feed or
follow us on Twitter to keep up to date with the latest posts and tutorials.
If you have any questions, or you can a think of a way to improve this class, please leave a comment!
Really simple inline Javascript validation
Just about any website or web application will require user input in one form or another. Whether it’s
filling in a contact form or entering profile details into a new application, handling input errors can be
the difference between a good or a bad user experience.
Have you ever filled in a huge form online, only to submit it and find that there was an error so you have
to start again? Frustrating, isn’t it? It is these kind of fundamental errors that stop people returning to
your website.
A much better way of solving this problem is to include inline validation that checks the user’s input as
she progresses. This alerts the user to any errors and allows her to correct her errors before proceeding
and losing her progress.
Inline validation powered by Javascript can be incredibly easy to implement, so there really is no excuse
for not making your user’s lives as easy as possible.
Here is a tutorial for building your own Javascript validation that you can use on any input on your
website or web application. I’ve intentionally kept it as easy, simple and lightweight as possible.
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Validation tutorial</title>
<script>
// JS
</script>
<form action="">
<fieldset>
<label for="name">Name</label>
<input type="text" name="name" id="name" />
</fieldset>
</form>
Next we need to add the onblur Javascript event to the input field. The onblur event allows you to run
Javascript code when the user clicks away from the field. In this case, we want to be able to validate
what the user has entered into the field, but we only want to do that when she has finished typing and
has moved on.
Update your input field so it looks like this.
<input type="text" name="name" id="name" onblur="validateName(name)" />
As you can see, I’ve already named the Javascript function that we are going to make in a minute and
I’ve passed in the name of the the field, in this case “name”.
In between the <script></script> tags at the top of the page, type the following code.
function validateName(x){
alert(document.getElementById(x).value);
}
Now save your file and open it in the browser. Enter some text into the input field and click away from
the field. An alert box should appear with the text you entered.
We created an input field. Added an onblur event which is triggered when the user clicks away
We then used a Javascript function to display the contents of the input in an alert box. So hopefully you
can see how the Javascript is run when it is triggered, and how we are able to get whatever the user has
typed into the input box and do something with it.
With this regex rule saved, we can then run a test on our input to see if what was entered matches our
defined rule.
Type the following code after the previous line.
if(re.test(document.getElementById(x).value)){
document.getElementById(x).style.background =’#ccffcc’;
return true;
}else{
document.getElementById(x).style.background =’#e35152′;
return false;
}
Here’s how the above code breaks down.
if(re.test(document.getElementById(x).value)){
We test to see if the input value matches our rule. If it does, we change the input box’s background to
green.
document.getElementById(x).style.background =’#ccffcc’;
return true;
But if it doesn’t, we turn the input box red.
}else{
document.getElementById(x).style.background =’#e35152′;
return false;
}
Save this out and refresh the page in your browser. You should now have a swanky input box that
validates and gives a visual feedback to the user to tell them if their input was accepted or not.
Including a prompt
We’ve added a huge amount of usability to our form already, but there is still more we can do.
Not every input field will have obvious rules. For example, you might have a username field where you
have a very precise set of allowed characters. In this instance, it is important to give your user some
kind of message to help them complete the form. Without this prompt, you are likely going to annoy
your user if they are repeatedly failing your validation test.
To add a validation prompt, add the following line of code to your form, just under your input field.
<span id="nameError" style="display: none;">You can only use alphabetic characters, hyphens and
apostrophes</span>
Next add the following line to the else branch of your if else statement in your Javascript.
document.getElementById(x + ‘Error’).style.display = "block";
Save your file and fresh your browser. You should now be given a prompt when you enter invalid
characters.
Finally add the following line to the if branch of your if else statement.
document.getElementById(x + ‘Error’).style.display = "none";
This will clean up the prompt message once the user corrects their mistake.
Validation on form submission
The validation you’ve added so far is great because it allows the user to correct their mistakes as they
progress. The next step is to prevent the form from being submitted if any of the validation rules are
broken.
This is handy because we don’t really want to allow our user to submit a form with invalid data. Once
the form is validated on the server side, it should spit it back out with an error message. However, we
can stop it from ever getting this far by validating on the client side too.
// Check name
if(!validateName(‘name’)){
document.getElementById(‘nameError’).style.display = "block";
error++;
}
This runs the validateName() function on the name input field. If it returns false we know that the input
field did not validate and so we display our error prompt and increase the error counter by 1.
Finally we create a little catch so if there are errors the form will not submit.
<fieldset>
<label for="email">Email</label>
<input type="text" name="email" id="email" onblur="validateEmail(value)" />
<span id="emailError" style="display: none;">You must enter a valid email address</span>
</fieldset>
Javascript
// Validate email
function validateEmail(email){
var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-
9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if(re.test(email)){
document.getElementById(’email’).style.background =’#ccffcc’;
document.getElementById(’emailError’).style.display = "none";
return true;
}else{
document.getElementById(’email’).style.background =’#e35152′;
return false;
}
}
Validate dropdown boxes
HTML
<fieldset>
<label for="animal">Favourite Animal</label>
<select name="animal" id="animal" onblur="validateSelect(name)">
<option value="">Animals</option>
<option value="cat">Cat</option>
<option value="dog">Dog</option>
<option value="badger">Badger</option>
</select>
<span class="validateError" id="animalError" style="display: none;">You must select your favourite
animal</span>
</fieldset>
Javascript
<fieldset>
<label for="hand">Left or Right handed?</label>
<ul>
<li>
<input type="radio" name="hand" id="left" value="Left" onblur="validateRadio(id)" />
<label for="left">Left handed</label>
</li>
<li>
<input type="radio" name="hand" id="right" value="Right" onblur="validateRadio(id)" />
<label for="right">Right handed</label>
</li>
</ul>
<span class="validateError" id="handError" style="display: none;">Which hand do you use?</span>
</fieldset>
Javascript
function validateRadio(x){
if(document.getElementById(x).checked){
return true;
}else{
return false;
}
}
Validate Checkboxes
<fieldset>
<label for="terms">Terms and Conditions</label>
<ul>
<li>
<input type="checkbox" name="terms" id="accept" value="accept" onblur="validateCheckbox(id)" />
<label for="accept">Accept our <a href="#">Terms and Conditions</a></label>
</li>
</ul>
<span class="validateError" id="termsError" style="display: none;">You need to accept our terms and
conditions</span>
</fieldset>
Javascript
function validateCheckbox(x){
if(document.getElementById(x).checked){
return true;
}
return false;
}
Validate your entire form
And finally, add the following code to your validateForm() function to validate your whole form when it
is submitted.
// Validate email
if(!validateEmail(document.getElementById(’email’).value)){
document.getElementById(’emailError’).style.display = "block";
error++;
}
// Validate Radio
if(validateRadio(‘left’)){
}else if(validateRadio(‘right’)){
}else{
document.getElementById(‘handError’).style.display = "block";
error++;
}
// Validate Checkbox
if(!validateCheckbox(‘accept’)){
document.getElementById(‘termsError’).style.display = "block";
error++;
}
The full code
Here is the full code.
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Validation tutorial</title>
<script>
function validateName(x)
{
// Validation rule
var re = /[A-Za-z -‘]$/;
// Check input
if(re.test(document.getElementById(x).value)){
// Style green
document.getElementById(x).style.background =’#ccffcc’;
// Hide error prompt
document.getElementById(x + ‘Error’).style.display = "none";
return true;
}else{
// Style red
document.getElementById(x).style.background =’#e35152′;
// Show error prompt
document.getElementById(x + ‘Error’).style.display = "block";
return false;
}
}
// Validate email
function validateEmail(email)
{
var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]
{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if(re.test(email))
{
document.getElementById(’email’).style.background =’#ccffcc’;
document.getElementById(’emailError’).style.display = "none";
return true;
}else{
document.getElementById(’email’).style.background =’#e35152′;
return false;
}
}
// Validate Select boxes
function validateSelect(x)
{
if(document.getElementById(x).selectedIndex !== 0)
{
document.getElementById(x).style.background =’#ccffcc’;
document.getElementById(x + ‘Error’).style.display = "none";
return true;
}
else
{
document.getElementById(x).style.background =’#e35152′;
return false;
}
}
function validateRadio(x)
{
if(document.getElementById(x).checked)
{
return true;
}
else
{
return false;
}
}
function validateCheckbox(x)
{
if(document.getElementById(x).checked)
{
return true;
}
return false;
}
function validateForm()
{
// Set error catcher
var error = 0;
// Check name
if(!validateName(‘name’))
{
document.getElementById(‘nameError’).style.display = "block";
error++;
}
// Validate email
if(!validateEmail(document.getElementById(’email’).value))
{
document.getElementById(’emailError’).style.display = "block";
error++;
}
// Validate animal dropdown box
if(!validateSelect(‘animal’))
{
document.getElementById(‘animalError’).style.display = "block";
error++;
}
// Validate Radio
if(validateRadio(‘left’))
{
}
else if(validateRadio(‘right’))
{
}
Else
{
document.getElementById(‘handError’).style.display = "block";
error++;
}
if(!validateCheckbox(‘accept’))
{
document.getElementById(‘termsError’).style.display = "block";
error++;
}
// Don’t submit form if there are errors
if(error > 0)
{
return false;
}
}
</script>
Number of columns 12
Nestable Yes
Above table demonstrates one important thing, applying any .col-sm-* class to an element will not only
affect its styling on small devices, but also on medium, large and extra large devices having screen width
greater than or equal to 540px, if a .col-md-*, .col-lg-* or .col-xl-* class is not present. Similarly, the .col-md-
* class will not only affect the styling of elements on medium devices, but also on large and extra large
devices if a .col-lg-* or .col-xl- class is not present.
Now the question arises how to create rows and columns using this 12 column responsive grid system.
The answer is pretty simple, at first create a container that acts as a wrapper for your rows and columns
using the .container class, after that create rows inside the container using the .row class, and to create
columns inside any row you can use the .col-*, .col-sm-*, .col-md-*, .col-lg-* and .col-xl-* classes. The
columns are actual content area where we will place our contents. Let's put all these things into real
action. Let's see how it actually works:
Example
Try this code »
<div class="container">
<!--Row with two equal columns-->
<div class="row">
<div class="col-md-6">Column left</div>
<div class="col-md-6">Column right</div>
</div>
Example
Try this code »
<div class="container">
<!--Row with three equal columns-->
<div class="row">
<div class="col-lg-4">Column left</div>
<div class="col-lg-4">Column middle</div>
<div class="col-lg-4">Column right</div>
</div>
Example
Try this code »
<div class="container">
<!--Row with two equal columns-->
<div class="row">
<div class="col">Column one</div>
<div class="col">Column two</div>
</div>
Example
Try this code »
<div class="container">
<!--Row with two equal columns-->
<div class="row">
<div class="col">Column one</div>
<div class="col">Column two</div>
</div>
Example
Try this code »
<div class="container">
<div class="row">
<div class="col-md-4 col-lg-3">Column one</div>
<div class="col-md-8 col-lg-6">Column two</div>
<div class="col-md-12 col-lg-3">Column three</div>
</div>
</div>
As you can see in the example above the sum of the medium grid column numbers (i.e. col-md-*) is 3 + 9
+ 12 = 24 > 12, therefore the third <div> element with the class .col-md-12 that is adding the extra columns
beyond the maximum 12 columns in a .row, gets wrapped onto a new line as one contiguous unit on the
medium screen size devices.
Similarly, you can create even more adaptable layouts for your websites using the Bootstrap's grid
column wrapping feature. Here're some ready to use Bootstrap grid examples.
In the above illustration there are total 12 content boxes in all devices, but its placement varies
according to the device screen size, like in mobile device the layout is rendered as one column grid
layout which has 1 column and 12 rows placed above one another, whereas in tablet it is rendered as
two column grid layout which has 2 columns and 6 rows.
Further, in large screen size devices like laptops and desktops it is rendered as three column grid layout
which has 3 columns and 4 rows and finally in extra large screen devices like large desktops it is
rendered as four column grid layout which has 4 columns and 3 rows.
Now the question is how we can create such responsive layouts using this Bootstrap new grid system.
Let's start with the primary target device. Suppose our primary target device is laptop or normal
desktop. Since our laptop layout has 3 columns and 4 rows i.e. 3x4 grid layout, so the HTML code for
making such grid structure would look something like this.
Example
Try this code »
<div class="container">
<div class="row">
<div class="col-lg-4"><p>Box 1</p></div>
<div class="col-lg-4"><p>Box 2</p></div>
<div class="col-lg-4"><p>Box 3</p></div>
<div class="col-lg-4"><p>Box 4</p></div>
<div class="col-lg-4"><p>Box 5</p></div>
<div class="col-lg-4"><p>Box 6</p></div>
<div class="col-lg-4"><p>Box 7</p></div>
<div class="col-lg-4"><p>Box 8</p></div>
<div class="col-lg-4"><p>Box 9</p></div>
<div class="col-lg-4"><p>Box 10</p></div>
<div class="col-lg-4"><p>Box 11</p></div>
<div class="col-lg-4"><p>Box 12</p></div>
</div>
</div>
If you see the output of the above example in a laptop or desktop which has screen or viewport width
greater than or equal to 992px but less than 1200px, you will find the layout has 4 rows where each row
has 3 equal columns resulting in 3x4 grid layout.
Now it's time to customize our layout for other devices. Let's first start by customizing it for tablet
device. Since inside the tablet our layout rendered as 2x6 grids (i.e. 2 columns and 6 rows). So, go ahead
and add the class .col-md-6 on every column.
Example
Try this code »
<div class="container">
<div class="row">
<div class="col-lg-4 col-md-6"><p>Box 1</p></div>
<div class="col-lg-4 col-md-6"><p>Box 2</p></div>
<div class="col-lg-4 col-md-6"><p>Box 3</p></div>
<div class="col-lg-4 col-md-6"><p>Box 4</p></div>
<div class="col-lg-4 col-md-6"><p>Box 5</p></div>
<div class="col-lg-4 col-md-6"><p>Box 6</p></div>
<div class="col-lg-4 col-md-6"><p>Box 7</p></div>
<div class="col-lg-4 col-md-6"><p>Box 8</p></div>
<div class="col-lg-4 col-md-6"><p>Box 9</p></div>
<div class="col-lg-4 col-md-6"><p>Box 10</p></div>
<div class="col-lg-4 col-md-6"><p>Box 11</p></div>
<div class="col-lg-4 col-md-6"><p>Box 12</p></div>
</div>
</div>
Tip: For convenience choose your primary target device and create layout for that device first after that
add classes to make it responsive for other devices.
Similarly, you can customize the layout for extra large devices like a large desktop screen by adding the
class .col-xl-3 on each column, as every row in our extra large device layout contains 4 columns. Here's
the final code after combining the whole process.
Example
Try this code »
<div class="container">
<div class="row">
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 1</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 2</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 3</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 4</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 5</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 6</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 7</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 8</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 9</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 10</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 11</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 12</p></div>
</div>
</div>
Tip: According to the above illustration there is no need to customize the layout for mobile phones;
since columns on extra small devices will automatically become horizontal and rendered as 1x12
column grid layout in absence of .col-* or .col-sm-* classes.
Example
Try this code »
<div class="container">
<div class="row">
<div class="col-sm-8">Column left</div>
<div class="col-sm-4">
<!--Column right with nested rows and columns-->
<div class="row">
<div class="col-12"></div>
</div>
<div class="row">
<div class="col-6"></div>
<div class="col-6"></div>
</div>
</div>
</div>
</div>
Example
Try this code »
<div class="container">
<div class="row justify-content-md-center">
<div class="col-md-3">Column left</div>
<div class="col-md-auto">Variable width column</div>
<div class="col-md-3">Column right</div>
</div>
<div class="row">
<div class="col">Column left</div>
<div class="col-auto">Variable width column</div>
<div class="col">Column right</div>
</div>
</div>
Example
Try this code »
<div class="container">
<div class="row align-items-start">
<div class="col">Column one</div>
<div class="col">Column two</div>
<div class="col">Column three</div>
</div>
<div class="row align-items-center">
<div class="col">Column one</div>
<div class="col">Column two</div>
<div class="col">Column three</div>
</div>
<div class="row align-items-end">
<div class="col">Column one</div>
<div class="col">Column two</div>
<div class="col">Column three</div>
</div>
</div>
Individual columns inside a row can also be aligned vertically. Here's an example:
Example
Try this code »
<div class="container">
<div class="row">
<div class="col align-self-start">Column one</div>
<div class="col align-self-center">Column two</div>
<div class="col align-self-end">Column three</div>
</div>
</div>
Note: You can skip the number in .col-* grid class and just use the .col class to create equal size columns
for all devices (extra small, small, medium, large, and extra large).
Horizontal Alignment of Grid Columns
You can use the classes .justify-content-start, .justify-content-center, and .justify-content-end to align the grid
columns horizontally at the left, center and right of a container, respectively. Let's check out the
following example to see how it works:
Example
Try this code »
<div class="container">
<div class="row justify-content-start">
<div class="col-4">Column one</div>
<div class="col-4">Column two</div>
</div>
<div class="row justify-content-center">
<div class="col-4">Column one</div>
<div class="col-4">Column two</div>
</div>
<div class="row justify-content-end">
<div class="col-4">Column one</div>
<div class="col-4">Column two</div>
</div>
</div>
Alternatively, you can use the class .justify-content-around to distribute grid columns evenly with half-
size spaces on either end, whereas you can use the class .justify-content-between to distribute the grid
columns evenly where the first column placed at the start and the last column placed at the end. Try out
the following example to see how it actually works:
Example
Try this code »
<div class="container">
<div class="row justify-content-around">
<div class="col-4">Column one</div>
<div class="col-4">Column two</div>
</div>
<div class="row justify-content-between">
<div class="col-4">Column one</div>
<div class="col-4">Column two</div>
</div>
</div>
Please check out the tutoiral on css3 flexbox to learn more about flex items alignment.
Example
Try this code »
<div class="container">
<div class="row">
<div class="col order-last">First, but ordered at last</div>
<div class="col">Second, but unordered</div>
<div class="col order-first">Last, but ordered at first</div>
</div>
</div>
You can also use the .order-* classes to order the grid columns depending on the order numbers. Grid
column with higher order number comes after the grid column with lower order number or grid
column with no order classes. It includes support for 1 through 12 across all five grid tiers.
Example
Try this code »
<div class="container">
<div class="row">
<div class="col order-4">First, but ordered at last</div>
<div class="col">Second, but ordered at first</div>
<div class="col order-1">Last, but ordered at second</div>
</div>
</div>
Example
Try this code »
<div class="container">
<div class="row">
<div class="col-sm-4"></div>
<div class="col-sm-8"></div>
</div>
<div class="row">
<div class="col-sm-8 offset-sm-4"><!--Column with 4 columns offset--></div>
</div>
</div>
You can also offset columns using the margin utility classes. These classes are useful in the situations
where the width of the offset is not fixed. Here's an example:
Example
Try this code »
<div class="container">
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-4 ml-auto"><!--Offset this column to right--></div>
</div>
<div class="row">
<div class="col-auto mr-auto"></div>
<div class="col-auto"><!--Move this column away from previous column--></div>
</div>
</div>
Note: You can use the class .col-auto to create columns that only take up as much space as needed, i.e.
the column sizes itself based on the contents.
Example
Try this code »
Example
Try this code »
<div class="container">
<!-- Break columns on all devices -->
<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>
<!-- Break columns on all devices except extra large devices -->
<div class="row">
<div class="col">.col</div>
<div class="col">.col</div>
<div class="w-100 d-xl-none"></div>
<div class="col">.col</div>
<div class="col">.col</div>
</div>
</div>
We hope you've understood the basics of new Bootstrap 4 grid system. In next few chapters you'll learn
how to create basic web page layouts using this flexbox grid system.