Always Visible Search Bar Shopify
Navigate to Customize > Header Section, then insert the following code into the Custom Liquid.
<style>
.search-modal__button {
display:none;
}
/* REMOVE THIS LINE TO HIDE ON DESKTOP
@media (min-width: 769px){
predictive-search-component{
display: none !important;
} }
@media (max-width: 768px){
.search-modal__button {
display: none !important;
} }
*/
</style>
<predictive-search-component
class="add-one predictive-search{% if class != blank %} {{ class | strip }}{% endif %}{% if search_position != blank %} predictive-search--{{ search_position }}{% endif %}"
style="--product-corner-radius: {{ settings.product_corner_radius | default: 8 | append: 'px' }}; --card-corner-radius: {{ settings.card_corner_radius | default: 8 | append: 'px' }};{% if settings.card_title_case == 'uppercase' %} --title-case: uppercase;{% endif %}"
data-section-id="predictive-search"
data-search-position="{{ search_position }}"
data-testid="{{ search_test_id }}"
data-active-color-scheme="{{ settings.popover_color_scheme }}"
role="search"
aria-label="{{ 'content.search_input_label' | t }}"
>
<form
action="{{ routes.search_url }}"
method="get"
role="search"
class="predictive-search-form"
ref="form"
on:keydown="/onSearchKeyDown"
>
<div class="predictive-search-form__header" style="position: relative;">
<div class="predictive-search-form__header-inner">
<label
for="{{ input_id | default: 'Search' }}"
class="visually-hidden"
>
{{- 'content.search_input_label' | t -}}
</label>
<input
class="search-input"
id="{{ input_id | default: 'Search' }}"
type="search"
name="q"
role="combobox"
aria-expanded="false"
aria-owns="predictive-search-results"
aria-controls="predictive-search-results"
aria-haspopup="listbox"
aria-autocomplete="list"
autocomplete="off"
placeholder="{{ 'content.search_input_placeholder' | t }}"
ref="searchInput"
on:input="/search"
on:keydown="/onSearchKeyDown"
on:focus="/expandSearch"
>
<input
name="options[prefix]"
type="hidden"
value="last"
>
<span class="svg-wrapper predictive-search__icon">
{{ 'icon-search.svg' | inline_asset_content }}
</span>
<button
type="button"
class="button-unstyled predictive-search__reset-button"
aria-label="{{ 'accessibility.reset_search' | t }}"
ref="resetButton"
hidden
onclick="
document.querySelector('#predictive-search-results')?.style.setProperty('display', 'none');
this.closest('form').querySelector('.search-input').value = '';
"
>
<span class="svg-wrapper predictive-search__reset-button-icon">
{{ 'icon-reset.svg' | inline_asset_content }}
</span>
<span class="predictive-search__reset-button-text">{{ 'actions.clear' | t }}</span>
</button>
</div>
<button
type="button"
class="button predictive-search__close-modal-button"
aria-label="{{ 'accessibility.close_dialog' | t }}"
on:click="dialog-component/closeDialog"
ref="closeModalButton"
style="position: absolute; top: 10px; right: 10px; z-index: 10;"
>
<span class="svg-wrapper" style="font-size: 20px;">×</span>
</button>
</div>
<div class="predictive-search-form__content-wrapper">
<div
class="predictive-search-form__content"
tabindex="-1"
id="predictive-search-results"
ref="predictiveSearchResults"
on:click="/handleModalClick"
>
{% render 'predictive-search-empty-state', products_test_id: products_test_id %}
</div>
<div class="predictive-search-form__footer">
<button
class="button button-primary predictive-search__search-button"
ref="viewAllButton"
>
{{ 'content.search_results_view_all' | t }}
</button>
</div>
</div>
</form>
</predictive-search-component>
<script>
document.addEventListener('DOMContentLoaded', function() {
const searchComponent = document.querySelector('predictive-search-component');
const searchResults = document.querySelector('#predictive-search-results');
const searchInput = document.querySelector('.search-input');
if (searchComponent && searchResults) {
let isSearchActive = false;
// Handle click outside to close search
document.addEventListener('click', function(event) {
// Check if the search results are visible and click was outside
if (isSearchActive && !searchComponent.contains(event.target)) {
// Click was outside the search component, close it
searchResults.style.display = 'none';
isSearchActive = false;
if (searchInput) {
searchInput.setAttribute('aria-expanded', 'false');
}
}
});
// Handle search input focus/click to show results
if (searchInput) {
searchInput.addEventListener('focus', function() {
if (this.value.length > 0 || searchResults.innerHTML.trim() !== '') {
searchResults.style.display = 'block';
isSearchActive = true;
this.setAttribute('aria-expanded', 'true');
}
});
searchInput.addEventListener('input', function() {
if (this.value.length > 0) {
searchResults.style.display = 'block';
isSearchActive = true;
this.setAttribute('aria-expanded', 'true');
}
});
// Also handle click on search input
searchInput.addEventListener('click', function() {
if (searchResults.style.display === 'none' || !isSearchActive) {
searchResults.style.display = 'block';
isSearchActive = true;
this.setAttribute('aria-expanded', 'true');
}
});
}
// Handle escape key to close search
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape' && isSearchActive) {
searchResults.style.display = 'none';
isSearchActive = false;
if (searchInput) {
searchInput.setAttribute('aria-expanded', 'false');
searchInput.blur(); // Remove focus from input
}
}
});
// Prevent clicks inside the search component from bubbling up
searchComponent.addEventListener('click', function(event) {
event.stopPropagation();
});
// Monitor when search results are shown by the theme's original functionality
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.target === searchResults && mutation.type === 'attributes' && mutation.attributeName === 'style') {
const display = window.getComputedStyle(searchResults).display;
if (display !== 'none') {
isSearchActive = true;
}
}
});
});
observer.observe(searchResults, {
attributes: true,
attributeFilter: ['style']
});
}
});
</script>
Vote Here