Blog

The Better Way to Modify Magento Layouts

In this article, I'm going to be covering what I believe to be a very effective way of modifying the layout of any Magento theme.

For several of the first Magento themes I built, I copied the layout files from the default or blank theme into the custom theme layout folder. I would then modify the layout files directly, editing or commenting out content in files like: catalog.xml, page.xml, checkout.xml, etc... I never liked editing these files directly, as I knew that when it came time to upgrade to a newer version of Magento that had upgraded the layout files, I'd have to merge the changes into the new layout files.

One day, I was digging through the Magento code relating to layout files and discovered a bit of code that made me realize that it was possible to just place a local.xml file in my custom theme's layout folder and have it loaded automatically by Magento. (this code is on line 283 in /app/code/core/Mage/Core/Model/Layout/Update.php in the fetchFileLayoutUpdates() method).

Due to Magento's brilliant tags, it's possible to do just about anything you want without having to edit any of the default layout files.

Before delving into the code, let's look at the advantages/disadvantages of this method:

Advantages

  • Allows you to upgrade themes without having to merge in changes
  • All custom layout changes are centralized, allowing developers to more easily make changes to custom theme elements

Disadvantages

  • At first, it's slower to use this method than hacking up the standard layout files directly
  • You will have one more place to look where the site might be pulling code (template phtmls, standard layout files, admin layout updates, AND local.xml)

Here is the slimmed down, commented local.xml from one of our recent projects:

<?xml version="1.0"?>
<layout version="0.1.0">
 
<default>
 
	<reference name="head">
		<!-- Magento looks in /skin/frontend/<INTERFACE>/<THEME>/js/buyprinting.js
		for this file -->
		<action method="addItem"><type>skin_js</type><name>js/buyprinting.js</name></action>
 
		<!-- This removes the item that was set in the page.xml file -->
		<action method="removeItem"><type>skin_js</type><name>js/iehover-fix.js</name></action>
 
		<!-- Magento looks in /js/prototype/element.storage.js for this file -->
		<action method="addJs"><name>prototype/element.storage.js</name></action>
 
		<action method="addCss">
<stylesheet>css/buyprinting.css</stylesheet></action>
	</reference>
 
	<reference name="header">
        <!-- This adds a CMS block that can be called from the template file
        associated with the header block. -->
		<block type="cms/block" name="cms_quick_help">
			<action method="setBlockId"><block_id>quick_help</block_id></action>
		</block>
 
        <!-- The remove tag removes the blocks with the specified name from the layout -->
		<remove name="top.menu"/>
		<remove name="store_language"/>
		<remove name="breadcrumbs"/>
	</reference>
 
	<reference name="top.nav">
		<remove name="catalog.topnav"/>
	</reference>
 
	<reference name="left">
		<remove name="left.newsletter"/>
		<remove name="left.permanent.callout"/>
		<remove name="catalogsearch.leftnav"/>
 
        <!-- When you use the remove tag, it removes any blocks with the specified name from
            the entire layout, regardless of the context. So, if I remove right.newsletter in
            the <default> context and that name is used in say the <catalog_product_view> context,
            then both blocks will be removed.  Because remove operates on the global context,
            you can only remove an element once.  Since <remove name="right.newsletter" /> is
            being called in catalogsearch.xml, we have to unset it, or else we'll get an error.
 
            The line below only unsets the block from the parent's context, not the global
            layout context -->
		<action method="unsetChild"><name>right.newsletter</name></action>
	</reference>
 
	<reference name="right">
        <!-- Some blocks have to be removed using remove, others via unsetChild.
            I've not spent the time digging into the code to figure out why -->
		<remove name="right.permanent.callout"/>
		<remove name="catalog.compare.sidebar"/>
		<remove name="left.reports.product.viewed"/>
		<action method="unsetChild"><name>sale.reorder.sidebar</name></action>
		<action method="unsetChild"><name>wishlist_sidebar</name></action>
		<action method="unsetChild"><name>right.reports.product.viewed</name></action>
		<remove name="cart_sidebar"/>
	</reference>
 
</default>
 
<!-- CATALOG PAGES -->
	<catalog_product_view><!-- 2columns-right -->
		<reference name="root">
			<action method="setTemplate"><template>page/2columns-left.phtml</template></action>
		</reference>
		<reference name="content">
			<reference name="product.info">
				<block type="cms/block" name="cms_product_info_tabs">
					<action method="setBlockId"><block_id>product_info_tabs</block_id></action>
				</block>
				<block type="catalog/product_view" name="product.clone_prices" as="prices" template="catalog/product/view/price_clone.phtml"/>
				<action method="unsetChild"><name>tierprices</name></action>
				<action method="unsetChild"><name>addto</name></action>
				<remove name="addto"/>
				<reference name="product.info.options.wrapper.bottom">
					<action method="unsetChild"><name>product.tierprices</name></action>
				</reference>
			</reference>
		</reference>
	</catalog_product_view>
 
</layout>

I hope with article has given you some direction as to how you can improve you Magento theming skills. If you have any additional tips/comments on coding layouts, please suggest them in the comments section.

Posted on February 23, 2010

Posted by Erik Hansen

Comments

vijaY's picture

THANKS

THANKS

Magento Ajax Add to Cart's picture

How do you have control over

How do you have control over number of products in the category ? Also, how to handle the out of stock notification indicator when you create custom layout ?

Dani's picture

Great tutorial for

Great tutorial for understanding the possiblities of the theme-topic ;-)

Sams's picture

Thank you for your

Thank you for your post!

Anybody knows how to restore left block which is removed on checkout-page via checkout.xml

I am using local.xml file, and need to show this left block which is not showing. Any help will be great!

Alex Knight's picture

Great help & better tutorial,

Great help & better tutorial, nice. can u provide some similar help for Joomla also ? Thanks in advance !!!

Rachel's picture

Love this! Building my first

Love this! Building my first site in Magento and this article is a life saver...thank you! :)

Shore's picture

Great post, used it to remove

Great post, used it to remove all the unnecessary javascript from the checkout pages.

Thanks

Pete

Rhondel's picture

I've tried, but I am not

I've tried, but I am not getting my local.xml file to override anything. Its like It is being completely ignored. I created a new theme (genesis), and in there created 3 new folders (template, layout and genesis) and in the layout folder i have my local.xml file. The contents of the file is:

<?xml version="1.0" encoding="UTF-8"?>

css/local.css

page/1column.phtml

1

I simply want to update the default layout of the pages and this is not happening at all, neither is anything (for instance, breadcrumbs) being removed. Can anyone advise me as to what the solution is?

Chuck's picture

If your local.xml is being

If your local.xml is being ignored, then your problem is probably the caching. Magento really loves to cache its layouts. If it had to compile everything for every request it would quickly grind to a halt.
Go to your admin page. System | Cache Management. Make sure "Configuration" cache is disabled. IMO it's best to turn off *all* caching while a site is in development.

Rhondel's picture

Some of the code was removed.

Some of the code was removed.

Peter Gross's picture

I am extremely impressed

I am extremely impressed thanks for sharing all information. It is a great post for the people to get the proper information.

Mike Jaggers's picture

Extremely awesome and helpful

Extremely awesome and helpful post for me... even about a year after you wrote it!! These layouts are tough to get the hang of, but your code example really helped me out.

You should write a book on templating Magento. Stuff like local.xml best practices and "stuff you need to know". I'd for sure buy it. ;)

Ivan's picture

@hartog actually in 1.5 the

@hartog actually in 1.5 the code has just been moved to a different method. Have a look in public function getFileLayoutUpdatesXml in the same file, line 418

dave's picture

Hello Great articles. How

Hello
Great articles.
How to unsetChil one block

Its possible ? or only emove is ok for this block ?
Thanks

rob's picture

hmm just a note here but

hmm just a note here but maybe it would be a good idea to dig into the source for this site and add "htmlspecialchars()"
to the php for the comment post. would make it a WHOLE lot easier on your commenters.

Magento Development's picture

So I got past my initial

So I got past my initial issues and I am successfully designing a theme based on your method.

nonymous's picture

from: catalog_product_vie

from:

catalog_product_view>

reference name="content">
reference name="product.info">
action method="unsetChild">addto
remove name="addto"/>

/reference>
/reference>

nonymous's picture

from:

from:

addto

nonymous's picture

Why are you doing both

Why are you doing both unsetChild-addto AND remove addto ? Was the unsetChild not enough ?

from:

addto

Andrew's picture

Is there a tag type similar

Is there a tag type similar to that specifies if the shopping cart has anything in it? For example if I only wanted to display the My Cart toplink if the cart had something in it. I've seen a few ways it can be done by editing the php core directly, but I don't want to to that.
Cheers
Andrew

Janzell's picture

I love the way you explain

I love the way you explain it. Thank you!

http://www.webdosh.net/2011/12/magento-adding-and-removing.html

reptilex's picture

third try with xhtml

third try with xhtml tags:

Hi,
I love your article and I kept everything clean with this. I know you worte this ages ago, but maybe someone can give me a hand with one problem. I cannot add a new reference between content and footer without changing page.xml. Do you know a way to do this?
It works when I change page.xml and add into the default layout and:
<block type="core/text_list" name="middlespace" as="middlespace" translate="label">
<label>middlespace</label>
</block>
Then I can use:
<reference name="middlespace">
<block type="core/template" name="three-teasers-home" template="page/html/three-teasers-home.phtml" after="-" />
</reference>
But I don’t want to change page.xml, can you help me out? Or maybe someone else?

reptilex's picture

Hi, I love your article and

Hi,
I love your article and I kept everything clean with this. I know you worte this ages ago, but maybe someone can give me a hand with one problem. I cannot add a new reference between content and footer without changing page.xml. Do you know a way to do this?
It works when I change page.xml and add into the default layout and:

middlespace


Then I can use:


But I don’t want to change page.xml, can you help me out? Or maybe someone else?

reptilex's picture

Hi, I love your article and

Hi,
I love your article and I kept everything clean with this. I know you worte this ages ago, but maybe someone can give me a hand with one problem. I cannot add a new reference between content and footer without changing page.xml. Do you know a way to do this?
It works when I change page.xml and add into the default layout and:

middlespace

Then I can use:

But I don't want to change page.xml, can you help me out? Or maybe someone else?

Pierre FAY's picture

if you want to create your

if you want to create your own magento blocks and insert it in a layout look at : http://www.about-magento.com/magento-create-block-44

Simon Bérubé's picture

I guess the code tag didn't

I guess the code tag didn't really work:

dark

Simon Bérubé's picture

Thanks for pointing out this

Thanks for pointing out this helpful technique. With the following code in local.xml, I was able to simply incorporate an alternate body style.

dark

Maybray Digital's picture

How do you control number of

How do you control number of products in the category view in Magento?

amitabh's picture

Hi ehansen, Thanks for

Hi ehansen,

Thanks for great article lots of things are cleared to me by this article.

Luthor's picture

Thanks for your helpful tip.

Thanks for your helpful tip. I have a question. Are there any way to determine the block position from layout.xml file based on module configuration? EX: i have config from backend to show one block at: left, right or not. So the layout file of this module will reference to left, right or not. How do i approach this?

Sorry for my poor English. Hope you understand.

Thanks and hope to hear from you soon.

Adam Moss's picture

Great article, one issue that

Great article, one issue that I've come across is when you need to reorder the JavaScript includes in .

How do you normally approach this?

Zahid's picture

@Thomas- Sorry for being dump

@Thomas- Sorry for being dump here. Are you referring to create a custom module for "another block". Please explain what do you mean by "new reference" and "another block".

Thomas Bennett's picture

@ Zahid - you should not be

@ Zahid - you should not be using a "static" block to fetch database content. You should create a new reference or create another block to pull it in.

Zahid's picture

Magento 1.5.0.1 version Dear

Magento 1.5.0.1 version
Dear hansen,
we have gone through all the posts, excellent discussion but couldn't solve our simple problem i guess.

we are simply trying to display a news ticker on the right column of our home page.We are successful in creating a static block on the right column from the admin interface but data of news updates is required to be fetched from database.we have no clue how to fetch and display data on our static block. Design guide doesn't say any thing on the topic.
A quick help is appreciated.

Pauwil's picture

@seif That is indeed

@seif That is indeed possible, if you copy the page refrence code to the xml you can change everything.

For example the category page is 'catalog_category_default'. You can find it if you look in your page source, it's attaced to you body class (don't forget to change the - with _ in the xml).

seif's picture

Hi . Thanks for this article

Hi .
Thanks for this article , well done .
Can i use local local.xml to force the template in every page to 3columns.phtml ?
Thanks !

Pauwil's picture

Thanks for this article it is

Thanks for this article it is very helpfull, i was looking for this kind of tutorial.

Question tough: For example if i want to remove the ''My Cart" link out of the top.link, what is the best way to do this? Because in the checkout.xml this is inserted using a so i can't remove this using of because it isn't a block (am i right or am i totally thinking wrong)?

Also how can i change the quantity of the upsell blocks on the product detail page using the local.xml

Thanks!

Steven's picture

Hi, this post has been quite

Hi, this post has been quite useful to me. Thank you.

I do have a question following from it, though. It seems like if you use a local.xml file that you would be updating the layout of every page with that theme.

If this is true, then every unique page would require a new theme. It seems like that would be bulky, time-consuming and difficult to update.

Is there a way to get the local.xml file to make different changes to the layout based upon the template which has been chosen for the particular page? Or have I misunderstood what Magento is doing?

Thanks

magento notes's picture

Custom Layout Update,it can

Custom Layout Update,it can work, thanks for your share.

skin_csscss/style.css

B John's picture

I am trying to move the

I am trying to move the breadcrumbs on the Product View Page, so that it appears just below the product name. Is there any way to achieve this. Thank you for your great tips.

Percy Dobbelsteyn's picture

@Jonathan_Hodges: Thanks,

@Jonathan_Hodges: Thanks, that worked like a charm. Didn't think of doing it that way. I found an article that in navigation.phtml loops through all cms pages and adds the cms-pages to the navigation. I think that fogged my "clear thinking". Happily, I posted my problem here and now I've got it working. Thanks again.

Jonathan Hodges's picture

@Percy: You could add your

@Percy: You could add your static block in the default layout handle and echo it in the top of the footer template. Then unset child in the footer block in the layout handles for My Account and Checkout pages.

Percy Dobbelsteyn's picture

I am wondering if the

I am wondering if the following is possible:

I want to add a static block to the bottom of the content (between content and footer) for all pages, except for the checkout pages and the "My Account" pages. All other pages, being all CMS, Catalog, Products.

It seems to me that there should be a possibility to set this in the local.xml layout file. Can you help me with that?

David Oliver's picture

@Conair:

Conair's picture

Hi I'm completely new to

Hi I'm completely new to magento. I just want to know where do i go to edit code. Is it through the Magento dashboard? Thanks i appreciate any help for this newbie.

Steve Hansen's picture

I am so confused. Sorry! I

I am so confused. Sorry! I cannot figure this out. Why is it so difficult to edit the top menu bar with cart, login, etc? What file do I go to so I can just edit it, or put a stupid breadcrumbs add-in to manage the links myself? Sorry, I have searched at least 30 blogs and not gotten an answer and everything I try crashed the site, been working at it for at least 6 hours now, and it is late and the pub under my office is having karaoke night to top it off. hahahahah! Thanks for any help.

beeplogic's picture

I think managing all custom

I think managing all custom updates via local.xml is a bad idea.

If your upgrading Magento you should still merge any changes to layout or template files. This method does not solve that issue, it only makes it more difficult to track down which files need to be merged. For instance, if an update include some new blocks in you really wouldn't be able to find out unless you went through all the diffs between magento and then your custom theme.

Your custom layout changes should be all in your custom_package/default (assuming version 1.4+ which falls back to base/default).

If you're running on a version of magento that falls back on base/default then it's possible to only update the necessary files in your custom package and theme directories. When you upgrade, you compare the changes between the old and new magento versions, check if any of those files exist in your custom theme and only merge those files.

I've stared a script to help speed up this process, https://github.com/rgranadino/Mage-Upgrade-Helper
As a bonus it can also scan app/code/local for php classes which extend core magento classes and inform you if they should be reviewed. Currently only runs on *nix systems due to the use of the diff command.

Ben's picture

@hartog actually in 1.5 the

@hartog actually in 1.5 the code has just been moved to a different method. Have a look in public function getFileLayoutUpdatesXml in the same file, line 418

mau's picture

Thank you for this tutorial,

Thank you for this tutorial, it´s really good. I was wondering if it´s possible to add simple text via local.xml, like a phone number, or an adress into the top.links section, I just can´t figure it out. Cheers!

Tom's picture

Ended up being a jQuery /

Ended up being a jQuery / Prototype conflict. I simply had to add jQuery.noConflict() at the end of my jquery.js file. I thought by replacing the $ with jQuery it would have fixed it originally.

Add comment

The content of this field is kept private and will not be shown publicly. If you have a Gravatar account associated with the e-mail address you provide, it will be used to display your avatar.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options