Skip to content

Alt om WordPress, webutvikling — og mer til

🔧 Hvordan gjøre et WordPress-tema WooCommerce-klart: en komplett guide for utviklere

🔧 Hvordan gjøre et WordPress-tema WooCommerce-klart: en komplett guide for utviklere

Bygger du ditt eget tema og vil integrere en butikk? Teknisk sett fungerer WooCommerce med ethvert tema, siden det bare er en plugin. Men «fungerer» betyr ikke «ser riktig ut»: produktoversikten brekker, sidekolonner flyter ut, og standardstiler krasjer med dine.

Problemet stikker dypere enn noen få CSS-regler. Fra og med WooCommerce 3.3 får et tema uten deklarert støtte forenklet visning via kortkoder og en advarsel i administrasjonspanelet. Du mister full kontroll over layouten.

Nedenfor finner du klare til bruk kodebiter som dekker alt fra å deklarere støtte til en levende handlekurv i menyen. Hver enkelt er testet på gjeldende WooCommerce-versjon og er organisert etter seksjon, fra grunnmur til finpuss.

💡 Rask oversikt:

  • For det første må temaet eksplisitt deklarere WooCommerce-støtte; uten dette vil ikke maloverstyringer og enkelte funksjoner aktiveres
  • Plasser kode i en egen fil (for eksempel inc/woocommerce.php) som kun lastes når pluginen er aktiv
  • Oppsett av butikkens rutenett krever to filtre: ett endrer antall kolonner, det andre legger til en klasse på body
  • Produktgalleri, zoom, lightbox og slider aktiveres gjennom separate add_theme_support-kall
  • Handlekurven i menyen må oppdateres via AJAX; bruk filteret add_to_cart_fragments

1. Grunnmur: deklarere støtte og sjekke om pluginen er aktiv

Først og fremst må temaet eksplisitt fortelle WooCommerce: «Jeg støtter deg.» Uten dette vil ikke pluginen aktivere maloverstyringer og viser en advarsel i administrasjonspanelet. Fra og med WooCommerce 3.3 får et tema uten deklarert støtte forenklet visning via kortkoder. Dette fungerer, men begrenser kontrollen din over layouten.

1add_action( 'after_setup_theme', function() {
2 add_theme_support( 'woocommerce' );
3} );

Det er viktig å bruke after_setup_theme-hooken fremfor init, slik det anbefales i WooCommerce-dokumentasjonen. Siden versjon 3.3+ kan du sende rutenettinnstillinger direkte:

1add_action( 'after_setup_theme', function() {
2 add_theme_support( 'woocommerce', array(
3 'thumbnail_image_width' => 150,
4 'single_image_width' => 300,
5 'product_grid' => array(
6 'default_rows' => 3,
7 'min_rows' => 2,
8 'max_rows' => 8,
9 'default_columns' => 4,
10 'min_columns' => 2,
11 'max_columns' => 5,
12 ),
13 ) );
14} );

Disse parameterne setter standardverdier for tilpasseren (WooCommerce → Produktbilder / Produktkatalog) og sparer brukere for å måtte konfigurere rutenettet manuelt.

Sjekke om pluginen er aktiv

Når du distribuerer et tema, kan du ikke bare dumpe WooCommerce-kodebiter på slutten av functions.php, fordi de vil forårsake en fatal feil hvis pluginen ikke er aktiv. Koden bør kun lastes når WooCommerce kjører:

1define( 'MYTHEME_WOOCOMMERCE_ACTIVE', class_exists( 'WooCommerce' ) );
2
3if ( MYTHEME_WOOCOMMERCE_ACTIVE ) {
4 require_once get_template_directory() . '/inc/woocommerce.php';
5}

Konstanten evalueres én gang, og deretter kan du hvor som helst i temaet ditt pakke inn kall i if ( MYTHEME_WOOCOMMERCE_ACTIVE ). Dette er ryddigere enn å kalle class_exists eller is_plugin_active hver gang.

2. Håndtere WooCommerce-stiler

WooCommerce leveres med tre CSS-filer: woocommerce-general, woocommerce-layout og woocommerce-smallscreen. Ideelt sett fjerner du dem ikke, men overstyrer dem i temaet ditt. På den måten knekker ikke tredjeparts WooCommerce-utvidelser som er avhengige av disse klassene. Men hvis du skriver alt fra bunnen av og vil ha full kontroll, her er hvordan du fjerner dem.

Fjern alle stiler på én gang:

1add_filter( 'woocommerce_enqueue_styles', '__return_empty_array' );

Eller fjern selektivt:

1function mytheme_remove_woo_styles( $styles ) {
2 unset( $styles['woocommerce-general'] );
3 unset( $styles['woocommerce-layout'] );
4 unset( $styles['woocommerce-smallscreen'] );
5 return $styles;
6}
7add_filter( 'woocommerce_enqueue_styles', 'mytheme_remove_woo_styles' );

I praksis er det andre alternativet mer vanlig: du fjerner woocommerce-layout (det prosentbaserte rutenettet), men beholder woocommerce-general (knapper, varsler, skjemaer) og overstyrer dem selektivt med din egen CSS ved hjelp av høyere spesifisitet.

3. Konfigurere butikksider

Hvor mange produkter som skal vises

Filteret loop_shop_per_page kontrollerer antall produkter på butikksiden og i arkiver (kategorier, stikkord):

1function mytheme_woo_posts_per_page( $cols ) {
2 return 12;
3}
4add_filter( 'loop_shop_per_page', 'mytheme_woo_posts_per_page' );

Antall kolonner i rutenettet

Her trengs to filtre. Å bare bruke loop_shop_columns er ikke nok: i motsetning til WooCommerce shortcodes (som har en wrapper med en columns-N-klasse), har ikke butikksidene denne klassen. Så vi legger den til i body:

1function mytheme_woo_shop_columns( $columns ) {
2 return 4;
3}
4add_filter( 'loop_shop_columns', 'mytheme_woo_shop_columns' );
5
6function mytheme_woo_shop_columns_body_class( $classes ) {
7 if ( is_shop() || is_product_category() || is_product_tag() ) {
8 $classes[] = 'columns-4';
9 }
10 return $classes;
11}
12add_filter( 'body_class', 'mytheme_woo_shop_columns_body_class' );

Nå kan du i CSS skrive selektorer som .columns-4 ul.products li.product, og de vil gjelde spesifikt for butikkrutenettet.

Butikktittel

WooCommerce viser «Shop» som tittel på butikksiden som standard. Hvis temaet ditt allerede håndterer arkivtitler, kommer denne duplikaten i veien:

1add_filter( 'woocommerce_show_page_title', '__return_false' );

Hvis du bruker the_archive_title(), kan du erstatte tittelen med navnet på butikksiden (satt i administrasjonspanelet):

1function mytheme_woo_archive_title( $title ) {
2 if ( is_shop() && $shop_id = wc_get_page_id( 'shop' ) ) {
3 $title = get_the_title( $shop_id );
4 }
5 return $title;
6}
7add_filter( 'get_the_archive_title', 'mytheme_woo_archive_title' );

4. Produktgalleri: zoom, lightbox og slider

Fra og med WooCommerce 3.0 ble et nytt produktgalleri introdusert, basert på FlexSlider, PhotoSwipe og jQuery Zoom. I versjonene 3.0-3.2 er det deaktivert som standard og krever eksplisitt aktivering. Fra og med 3.3 er galleriet aktivert for temaer som ikke er WooCommerce-temaer, og deaktivert for temaer som erklærer støtte; du aktiverer komponentene du trenger selv:

1add_theme_support( 'wc-product-gallery-slider' );
2add_theme_support( 'wc-product-gallery-zoom' );
3add_theme_support( 'wc-product-gallery-lightbox' );

Du kan aktivere bare noen funksjoner: for eksempel slider og zoom, ja, men erstatte lightboxen med din egen Fancybox-løsning. Hvert direktiv laster sine egne skript, så ikke aktiver det du ikke trenger.

Antall kolonner for galleriminiatyrer (under hovedproduktbildet):

1function mytheme_woo_product_thumbnails_columns() {
2 return 4;
3}
4add_action( 'woocommerce_product_thumbnails_columns', 'mytheme_woo_product_thumbnails_columns' );

5. Relaterte produkter og kryssalg/oppsalg

På produktsiden viser WooCommerce blokkene «Relaterte produkter» og «Du vil kanskje også like» (oppsalg). Antall og rutenett konfigureres separat.

Hvor mange relaterte produkter som skal vises:

1function mytheme_woo_related_posts_per_page( $args ) {
2 $args['posts_per_page'] = 4;
3 return $args;
4}
5add_filter( 'woocommerce_output_related_products_args', 'mytheme_woo_related_posts_per_page' );

Kolonner for oppsalgs- og relaterte blokker (samme historie som med butikkrutenettet): vi endrer både kolonnene og klassen på body:

1function mytheme_woo_single_loops_columns( $columns ) {
2 return 4;
3}
4add_filter( 'woocommerce_up_sells_columns', 'mytheme_woo_single_loops_columns' );
5
6function mytheme_woo_related_columns( $args ) {
7 $args['columns'] = 4;
8 return $args;
9}
10add_filter( 'woocommerce_output_related_products_args', 'mytheme_woo_related_columns', 10 );
11
12function mytheme_woo_single_loops_columns_body_class( $classes ) {
13 if ( is_singular( 'product' ) ) {
14 $classes[] = 'columns-4';
15 }
16 return $classes;
17}
18add_filter( 'body_class', 'mytheme_woo_single_loops_columns_body_class' );

Merk at woocommerce_output_related_products_args har to filtre med ulik prioritet: mytheme_woo_related_posts_per_page (standard 10) endrer posts_per_page, og mytheme_woo_related_columns (prioritet 10) endrer columns. De kommer ikke i konflikt fordi de jobber med ulike nøkler i den samme $args-tabellen.

6. Paginering og salgsmerke

Du kan erstatte pagineringen med ditt temas ikoner:

1function mytheme_woo_pagination_args( $args ) {
2 $args['prev_text'] = '<i class="fa fa-angle-left"></i>';
3 $args['next_text'] = '<i class="fa fa-angle-right"></i>';
4 return $args;
5}
6add_filter( 'woocommerce_pagination_args', 'mytheme_woo_pagination_args' );

Bytt ut Font Awesome-klassene med dine egne ikonklasser eller direkte SVG-er.

Teksten på salgsmerket (Sale!) er enkel å overstyre. Dette er nyttig for nettsteder på andre språk eller rett og slett for å fjerne utropstegnet:

1function mytheme_woo_sale_flash() {
2 return '<span class="onsale">' . esc_html__( 'Sale', 'woocommerce' ) . '</span>';
3}
4add_filter( 'woocommerce_sale_flash', 'mytheme_woo_sale_flash' );

For andre språk, erstatt 'Sale' med din oversettelse. Oversettelsen vil bli plukket opp automatisk hvis du har WooCommerce MO-filer for det språket.

7. Dynamisk handlekurv i menyen

Dette er trolig det mest etterspurte elementet i ethvert butikktema: et handlekurvikon i navigasjonen med gjeldende totalsum. Implementeringen består av tre deler: å legge til elementet i menyen, generere handlekurvens HTML og AJAX-oppdatering.

1// Adding the link to the menu
2function mytheme_add_menu_cart_item( $items, $args ) {
3 if ( $args->theme_location === 'primary' ) {
4 $css_class = 'menu-item menu-item-type-cart menu-item-type-woocommerce-cart';
5 if ( is_cart() ) {
6 $css_class .= ' current-menu-item';
7 }
8 $items .= '<li class="' . esc_attr( $css_class ) . '">';
9 $items .= mytheme_menu_cart_item();
10 $items .= '</li>';
11 }
12 return $items;
13}
14add_filter( 'wp_nav_menu_items', 'mytheme_add_menu_cart_item', 10, 2 );
15
16// Cart HTML
17function mytheme_menu_cart_item() {
18 $cart_count = WC()->cart->cart_contents_count;
19 $css_class = 'wpex-menu-cart-total wpex-cart-total-' . intval( $cart_count );
20 $url = $cart_count ? WC()->cart->get_cart_url() : wc_get_page_permalink( 'shop' );
21 $html = WC()->cart->get_cart_total();
22 $html = str_replace( 'amount', '', $html );
23
24 return '<a href="' . esc_url( $url ) . '" class="' . esc_attr( $css_class ) . '">'
25 . '<span class="cart-icon"></span>'
26 . wp_kses_post( $html )
27 . '</a>';
28}
29
30// AJAX fragment update
31function mytheme_menu_cart_link_fragments( $fragments ) {
32 $fragments['.wpex-menu-cart-total'] = mytheme_menu_cart_item();
33 return $fragments;
34}
35add_filter( 'add_to_cart_fragments', 'mytheme_menu_cart_link_fragments' );

Kritisk punkt: **ikke pakk inn disse funksjonene i **is_admin(). AJAX-forespørsler fra handlekurven kommer via admin-ajax.php, og hvis funksjonen ikke er tilgjengelig i admin-konteksten, vil prisoppdateringen i menyen rett og slett ikke fungere. Bytt ut theme_location med din menyidentifikator (primary i eksempelet).

8. Alternativ tilnærming: woocommerce.php-malen

Krokene beskrevet ovenfor er den mest fleksible og oppdateringssikre metoden. Men hvis du trenger å radikalt overhale hele butikk- og produktsideomslaget, finnes det en vei via en separat mal.

Opprett en woocommerce.php-fil i temaets rot (en kopi av page.php) og erstatt hovedsløyfen med et kall til woocommerce_content():

1<?php
2get_header(); ?>
3
4<div id="primary" class="content-area">
5 <main id="main" class="site-main">
6 <?php woocommerce_content(); ?>
7 </main>
8</div>
9
10<?php get_footer();
11

Denne metoden er enklere, men den har en kostnad: én mal for alle WooCommerce-sider (butikken, kategorier og produktdetaljer). Finjustering (forskjellige rutenett, forskjellige sidekolonner på ulike sider) blir vanskeligere. Velg denne tilnærmingen bare hvis ditt nåværende tema virkelig ikke kommer overens med WooCommerce på markeringsnivå, og du er forberedt på å akseptere begrensningene.

⁉️🤔 Ofte stilte spørsmål

Er det obligatorisk å fjerne WooCommerces standardstiler?

Ikke obligatorisk. En tryggere tilnærming er å beholde dem og overstyre selektorer i temaet ditt med høyere spesifisitet. Dette bevarer kompatibilitet med utvidelser som er avhengige av standard WooCommerce-klasser. Fullstendig fjerning (__return_empty_array) er kun berettiget hvis du bygger et butikktema fra bunnen av og vet med sikkerhet at ingen tredjeparts plugins vil legge til elementer som er stylet for WooCommerce. I de fleste tilfeller er det nok å selektivt deaktivere woocommerce-layout (prosentrutenettet kommer i konflikt med flexbox og grids i moderne temaer) mens du beholder woocommerce-general og woocommerce-smallscreen og nøye overstyrer dem gjennom CSS-kaskaden. Dette gir deg et rent rutenett uten å miste kompatibilitet.

Hvorfor fungerer ikke endring av kolonner i butikken?

Fordi loop_shop_columns-filteret alene ikke er nok. WooCommerce bruker .columns-N-klasser på wrapperen for å få rutenettet til å fungere, og de legges automatisk til kun på shortcodes ([products columns="4"]). På butikksider og arkiver eksisterer ikke denne wrapperen, så du må legge til klassen på body via body_class. De to filtrene fra seksjon 3 løser dette problemet fullstendig.

loop_shop_columns-filteret endrer PHP-variabelen som WooCommerce sender til malen, men CSS-rutenettet avhenger av wrapper-klassen. Uten columns-4-klassen på body har ikke stilene dine for ul.products li.product noen kontekstselektor og vil enten ikke gjelde eller treffe alle produktlister på tvers av nettstedet.

Må jeg bygge om temaet etter en WooCommerce-oppdatering?

Hvis du bruker hooks (alle kodebitene fra denne artikkelen), nei. Hooks endres ekstremt sjelden. Hvis du overstyrer maler (filer fra woocommerce/templates/), ja, da må du sammenligne kopiene dine med de gjeldende versjonene etter hver større oppdatering. Dette er nøyaktig grunnen til at den offisielle dokumentasjonen anbefaler hooks som den foretrukne tilpasningsmetoden.

Hooks er en kontrakt. WooCommerce garanterer deres stabilitet mellom versjoner. Maler er en implementasjon som kan endres når som helst: nye actions legges til, markup endres, klasser får nye navn. I de fem årene disse hookene har eksistert (loop_shop_columns og woocommerce_output_related_products_args), har signaturen deres aldri endret seg, mens filen content-product.php har blitt oppdatert dusinvis av ganger i samme periode.

Kan jeg bruke is_admin() for å beskytte handlekurvfunksjoner?

Nei, og dette er en vanlig felle. WooCommerce AJAX-forespørsler (legg i handlekurv, oppdater antall) behandles gjennom admin-ajax.php; i denne konteksten returnerer is_admin() true. Hvis du pakker inn handlekurvfunksjoner i if ( ! is_admin() ), vil AJAX-fragmentoppdateringer (add_to_cart_fragments) slutte å fungere, og totalen i handlekurvikonet vil ikke endres uten en sideoppdatering.

Innpakning i ! is_admin() bør kun brukes for ting som ikke skal kjøres i admin (front-end HTML-output), men AJAX-handlerfunksjoner må alltid være tilgjengelige. For koden i seksjon 7, ikke bruk is_admin() i det hele tatt. WooCommerce selv kaller de nødvendige tilbakekallingene gjennom sin AJAX-handler, og begrensningen vil ødelegge logikken.

Hvordan legger jeg til WooCommerce-støtte i et blokktema (FSE)?

For blokktemaer har støtteerklæringen ikke endret seg: den samme add_theme_support('woocommerce'). Men i stedet for hooks og overstyring av PHP-maler, jobber du i Nettstedsredigering: WooCommerce tilbyr blokker (Produkter, Produktsøk, Handlekurv, Kasse) som du setter inn i maler via Appearance → Editor. Finjustering gjøres gjennom theme.json og CSS-variabler.

Blokktemaer endrer fundamentalt tilnærmingen: du skriver ikke PHP-hooks for layout, men setter visuelt sammen sider fra ferdige WooCommerce-blokker. Men grunnlaget (add_theme_support i functions.php) forblir det samme. For finjusteringer som ikke kan gjøres med blokker (for eksempel egendefinert tekst på «Legg i handlekurv»-knappen), fungerer de gode gamle filtrene fra denne artikkelen også i FSE-temaer.

Hvilken strategi du bør velge for prosjektet ditt

Hvis du forbedrer et eksisterende tema, start med trinn 1 og 2: erklær støtte og konfigurer rutenettet. I de fleste tilfeller er dette nok til å få butikken til å se anstendig ut. Legg deretter bare til rettelsene som løser spesifikke problemer: et ødelagt galleri, stygg paginering, manglende handlekurv i menyen.

Hvis du skriver et tema fra bunnen av for salg eller distribusjon, gå gjennom hele listen. Hvert element legger til noe brukere forventer av et butikktema «rett ut av esken»: et tilpassbart rutenett, zoom på produkter, et levende handlekurvikon. Legg koden i inc/woocommerce.php og last den basert på konstanten. På denne måten fungerer temaet like godt som både en blogg og en butikk.

Utgangspunktet er alltid det samme:

1add_action( 'after_setup_theme', function() {
2 add_theme_support( 'woocommerce' );
3} );

Åtte linjer. Alt annet er detaljer som skiller et «kompatibelt» tema fra et «spesialbygd» et.