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 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.
First, run npm init vue@latest
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.
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.
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:
<template> <input type="text" v-model="input" placeholder="Search fruits..." /> <div class="item fruit" v-for="fruit in filteredList()" :key="fruit"> <p>{{ fruit }}</p> </div> <div class="item error" v-if="input&&!filteredList().length"> <p>No results found!</p> </div> </template>
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.
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) => fruit.toLowerCase().includes(input.value.toLowerCase()) ); } </script>
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.
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 svgrepo.com or flaticon.com.
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:
<style> @import url("https://fonts.googleapis.com/css2?family=Montserrat&display=swap"); * { 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; } </style>
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.
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:
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.
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 — start monitoring for free.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowValidating and auditing AI-generated code reduces code errors and ensures that code is compliant.
Build a real-time image background remover in Vue using Transformers.js and WebGPU for client-side processing with privacy and efficiency.
Optimize search parameter handling in React and Next.js with nuqs for SEO-friendly, shareable URLs and a better user experience.
Learn how Remix enhances SSR performance, simplifies data fetching, and improves SEO compared to client-heavy React apps.
One Reply to "How to create a search bar in Vue"
Why you won’t use computed for that? Calling logic in template renderer is generally bad idea.