Madars Bišs Madars Bišs (aka Madza) is a technical writer. In his spare time, he loves to explore new topics and contribute to open-source web development.

How to create a search bar in Vue

5 min read 1593

Vue Logo Over Green Background

Table of Contents

The internet is a vast ocean of information. In order to easily find the information we’re looking for, we rely on search bars, which are used in almost every app or website.

In this tutorial, we will build a custom search bar in Vue.js, an incredibly useful JavaScript framework for building fast and lightweight user interfaces.

Search Bar Fruits

Search bars come in many different shapes and forms. Our search bar example will filter an existing list of fruits, and you’ll learn how to build the layout, create logic, and style the search bar.

In our case, there will not be any complex algorithm to process the search query, but we will use a simple function to filter out the result by the query the user enters.

To improve the UX, the results will be returned in real-time, meaning they will be updated as the user types, with no need to click on anything to submit the search query to execute.

We will also track the scenarios, when there are no results for the search query, by returning an informative message to the user.

Setting up Vue

First, run npm init [email protected] in your terminal. This will execute create-vue, an official scaffolding tool by Vue to create fully-functional Vue projects.

You will be asked to give your project a name in the terminal wizard. Let’s call our app vue-search-app. When asked for further configuration of the project, press enter for all of the options.

After that, run cd vue-search-app and npm install to set all the necessary dependencies for the project.

We made a custom demo for .
No really. Click here to check it out.

Next, run npm run dev, which will start a dev server for your new Vue app. You can access it by opening http://localhost:3000 in your browser.

New Vue App

Creating the search bar component in Vue

Navigate to the src folder and find the App.vue file. We will write everything from scratch, so make sure you first remove all the content from App.vue. Then, include the following code:

   <input type="text" v-model="input" placeholder="Search fruits..." />
  <div class="item fruit" v-for="fruit in filteredList()" :key="fruit">
    <p>{{ fruit }}</p>
  <div class="item error" v-if="input&&!filteredList().length">
     <p>No results found!</p>

In Vue, all the Single-File Components must be wrapped in the template tag. Vue is going to compile everything inside it into the Virtual DOM.

We also created the input field itself. We set the type to text because we will enter the search queries inside it. We also added a built-in directive v-model to it, which will allow us to create a two-way binding between the typed-in value and data property. We also included a custom placeholder value that hints the user to perform a search action.

Then, we created the search items that will be returned. We used the built-in v-for directive to render a list of items in a paragraph based on a fruits array, which we will create in the next section. We also passed the :key attribute, which is a recommended practice when looping through elements in VueJS.

Finally, we created an error element that will be displayed if there are no results for the search query. For this, we used the built-in v-if directive to check if there is an input typed in and no results from the filter function. If both conditions are satisfied, the element is rendered.

For both div elements, we also included class attributes, so we can style them later. Both of them will contain the item class, while the fruit and error classes will be used to assign the different styling rules.

Adding data and logic

In order to add data and logic to the component, we will write some JavaScript. Vue allows us to write it in the same App.vue file by wrapping it in the <script> tags.

Under the template tags we created previously, include the following code:

<script setup>
import { ref } from "vue";
let input = ref("");
const fruits = ["apple", "banana", "orange"];
function filteredList() {
  return fruits.filter((fruit) =>

We first included the setup in the opening <script> tag, which is a compile-time syntactic sugar introduced in Vue v3.2 that allows us to write code with less boilerplate.

Then, we imported the ref attribute, which will let us store the user input in the search bar. We created a new variable input that will use the imported ref just for this cause.

Next, we created the fruit array, which will hold the data we will loop through. Normally, the data would come from the database, but for this tutorial, we will use simple dummy data.

Finally, we created a filteredList function that will check the user input again in each word in the fruits array and will return only those elements that include the search query.

If we check the browser, we should now be presented with an unstyled functional search bar.

Search Bar Unstyled

Importing the search icon

Vue uses a straightforward file structure for assets in your projects. Inside src, you will find the assets folder, where you can include the static assets you want to use. To access them, simply provide the path from the file, such as assets/image.svg in App.vue.

In our app, we will use an SVG search icon to make the search input area more appealing to the eye and improve the UI by highlighting the input area for search. You can download some nice search icons on sites like or

After it downloads, rename the icon search-icon.svg and put it into the assets folder.

We can style our search bar directly in the App.vue file. The only requirement is that all the style rules must be wrapped inside <style> tags.

Under the <script> tags we created previously, include the following style rules:

@import url("");

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  font-family: "Montserrat", sans-serif;

body {
  padding: 20px;
  min-height: 100vh;
  background-color: rgb(234, 242, 255);

input {
  display: block;
  width: 350px;
  margin: 20px auto;
  padding: 10px 45px;
  background: white url("assets/search-icon.svg") no-repeat 15px center;
  background-size: 15px 15px;
  font-size: 16px;
  border: none;
  border-radius: 5px;
  box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px,
    rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;

.item {
  width: 350px;
  margin: 0 auto 10px auto;
  padding: 10px 20px;
  color: white;
  border-radius: 5px;
  box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px,
    rgba(0, 0, 0, 0.06) 0px 1px 2px 0px;

.fruit {
  background-color: rgb(97, 62, 252);
  cursor: pointer;

.error {
  background-color: tomato;

At the top of the style rules, we used import syntax to import the Montserrat font so we can use it in our search component. You can pick one of the many alternatives in Google fonts — all of them are free.

We then created custom reset rules for all the elements used in our app so that there are no default values for styling and that the app looks the same on all the browsers. We removed the default padding and margin and set the box-sizing to include padding and margin in the width and height, as well as set each element to use the imported Montserrat font.

Then, we set the body to use the entire height of the screen, added some padding to it, and set the background color as a light shade of blue.

For the input element, we set the specific width, added some margin and padding, and set the font size. We used the background property to set the background color, imported the search icon, and positioned it in the input field. We also removed the custom border, set the corners to be slightly rounded, and added a nice shadow effect for the input.

For the returned elements, we set a specific width and added some margin and padding. We set the corners to be slightly rounded and included a shadow effect, and we set the font color to be white.

Finally, we gave fruit and error some separate styling rules for the background color and set the cursor to turn into a pointer when hovering over fruit items.

Testing the search bar in Vue

Now, check if your dev server is still running. If it is, visit the browser and open http://localhost:3000 again. If the server is not working, run the command npm run dev first.

You should be presented with a fully functional and designed search bar that lets you filter out the items as you write. Try to test it with truthy and faulty values to see if it handles both cases:

Completed Search Bar


In this tutorial, we created a fully functional search bar. We reviewed directive concepts, such as data binding, looping, conditional rendering, and using refs to store the input values provided by the user.

We also avoided any styling and component libraries and instead, created our own custom styling from scratch. We also learned how you can include your own icons in the input bar.

Hopefully, you learned something useful and the next time you work on a Vue project, you’ll know how to implement a search bar to help your users find the content they are looking for.

Experience your Vue apps exactly how a user does

Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket.

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens in your Vue apps including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.

The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error, and what state the application was in when an issue occurred.

Modernize how you debug your Vue apps - .

Madars Bišs Madars Bišs (aka Madza) is a technical writer. In his spare time, he loves to explore new topics and contribute to open-source web development.

One Reply to “How to create a search bar in Vue”

  1. Why you won’t use computed for that? Calling logic in template renderer is generally bad idea.

Leave a Reply