The Options Framework Theme has all the code included to build a out a full featured options panel. It’s a bundled version of the Options Framework Plugin for those folks who want to build the options directly into the theme (rather than relying on a plugin).

This project was released long before the Customizer was a part of WordPress. The Customizer is now the recommended way to add theme options and you can read more about it here.

Available Options

  • text
  • textarea
  • checkbox
  • select
  • radio
  • upload (an image uploader)
  • images (use images instead of radio buttons)
  • background (a set of options to define a background)
  • multicheck
  • color (a jquery color picker)
  • typography (a set of options to define typography)
  • editor


Copy the “inc” directory, options.php, and the code snippet in functions.php from the “Options Framework Theme” into the theme of your choice. Hack away. You can also watch the video above to see how it is done.

When to Use Theme Version vs. Plugin Version

The code is 99% the same between the plugin and theme version. If you can do what you need with the plugin version, I think that’s the best route. If you find that you need to make significant modifications that aren’t possible with the plugin, go ahead and use the theme version.

Change the Menu Location

It’s highly recommended that you leave theme options under the “Appearance” menu where users expect them.

But, if you do decide to change the menu location it will break the media uploader. This is because the media uploader scripts are enqueued on $of_page= ‘appearance_page_options-framework’ in options-medialibrary-uploader.php. If you change the name or location of the menu, you’ll need to update the hook to be accurate, e.g. $of_page= ‘toplevel_page_options-framework’ and those scripts will load properly again.

Sanitization Filters

If you’re interested in how the options data is verified, or if you’re wondering why your script and embed tags are stripped out in the Options Framework, read this post.

Can I Use This Code in Commercial Themes

Yes! This code is 100% GPL. Please read the included license for more details.

Development Version on GitHub

The development version of the Options Framework Theme is available on GitHub.

Additional Tutorials

The demo themes associated with these tutorials are also available on GitHub.

862 thoughts on “ Options Framework Theme ”

  1. Hi! In order to give my users a help link (?) I am adding an “” attribute to the description of each element I am adding to the options file. That should call a lightbox with an image. In order for it to work I need to call it with a special “id” or “rel” element which for some reason is being stripped out leaving just the “link” element.

    I have looked into the sanitation function for any reference but couldn’t find it.

    Any idea how can I keep my “a” element with the “rel” attribute?


    1. The most recent version of the Options Framework plugin allows $allowedtags. I’ll push out an update to the theme version when I have some time. You’re welcome to grab it from here though in the meantime: I’m not sure if “rel” is a supported attribute, but if not you can always override it and use a different sanitization for add_filter( ‘of_sanitize_info’, ‘of_sanitize_allowedtags’ ).

      1. i made a modification to the code, where you add “tooltip” => “this is tooltip” and it prints some icon on same line as h4 (title of field).. it uses flowplayer’s tooltip.. on line 50 of options-interface.php i added:
        if ( isset( $value['tooltip'] )) {
        $value['tooltip'] = '?';

        and then just add $value['tooltip'] where you want tooltip to appear…

      2. if ( isset( $value[‘tooltip’] )) {
        $value[‘tooltip’] = ‘<div class=”alignright tool” style=”color:red” title=”‘ . $value[‘tooltip’] . ‘”>?</div>’;

        forgot to convert it…

  2. Hi Devin, thanks for this great framework!
    I’m a newbie, then have a question for you:

    I want to check the multicheck categories and multicheck pages,
    how can I write the code?
    It is easy to choose one category, and one page, how can I write the code to choose 2 or more categories?

    1. I have checked the image you posted. The theme option is not really needed for what you want to implement. You just need to create a template file and named it “category-SLUG.php”* where slug is the slug name of the category.

  3. Great framework! Easy to use and enough options to make a functional options panel :)

    Good job.

    How about the future plans, are you going to develop this much further? If so I’m definitely going to support your efforts.

    1. Yep. I plan to keep supporting it. I am thinking of adding functionality to have multiple metaboxes under a single tab but haven’t had time to work on it yet.

    1. If you put this function in your functions.php file

      * Function to get attachment id from src
      function get_attachment_id_from_src( $image_src ) {
      global $wpdb;
      $query = "SELECT ID FROM {$wpdb->posts} WHERE guid='$image_src'";
      $id = $wpdb->get_var($query);
      return $id;

      Then you can use wp_get_attachment_image to output the image.

  4. Quick question, in the background default array, the repeat part for an image is set as:
    ‘repeat’ => ‘repeat’ …..but how do I make the default to be Repeat Horizontally (repeat-x)? I tried this but it doesn’t show in the options panel, only the original “repeat” does. Are the options not: Repeat All, Repeat Horizontally, Repeat Vertically, etc, as I see in the options drop down choices? I figured the default setting I want would be changed to this:
    ‘repeat’ => ‘Repeat Horizontally’
    But when I do this, it doesn’t show this. I actually have a theme where I have two background settings (just different ID’s) .Thanks in advance.

  5. Is there any way add another menu page? I tried to copy this function function optionsframework_add_page(), new page was added but it appears to be duplicate of what I already have. MY goal is to break all the options into multiple submenus… Thanks

    1. Not without some serious customization. The tabs allow you have different sections though. It would probably be fairly easy to add submenus that directly loaded one of the tabs.

      1. Dear Devin,

        Tim here, and I’d like to say that this is a very good options frmework and has made my job a lot easier. I have incorporated your options framework into a current theme I’m working on for a client, but I’m having a few problems.

        The js files are not loading.
        uploader and colorpicker and cutom js are loading in the admin header, because I can see it in the page source, but they are still not working.

        can you assist?

    2. Thanks Devin,

      but when I checked this morning, the problem was gone, don’t know what was going on but it is working now. The other problem I’m having is working with the typography.

      I used the example directly from the index.php

      <?php $typography = of_get_option('example_typography');
      if ($typography) {
      echo 'Some sample text in your style';

      echo '';
      foreach ($typography as $i=>$param) {
      echo ''.$i . ' = ' . $param.'';
      echo '';
      } else {
      echo "no entry";
      } ?>

      There was a syntax error expecting ‘,’ or ‘;’ on line 42
      line 42 is starting at the echo ‘<span style line
      And it did work for me, any reason why?

  6. I Freakin Love it.

    Thanks so much for this. After I started getting the hang of how everything works, my production started flying. I’ll be sure to keep you posted with what I create using this.

    Thanks again ;)

  7. I am looking to change the theme options page from appearance to the main admin page. I have modified this in option-framework.php by removing: ‘parent’ => ‘appearance’ and add_theme_page

    The Uploader is now not working, and I understand that I need to change the link to the scripts in options-medialibrary-uploader.php but not sure which. Can you possibly tell me what link would need to be changed? Many Thanks

    1. Hi Devin, I am still struggling to get this working as I can’t figure out what link needs to be updated in the code. Any help would be really appreciated

      1. @Matti

        you need to change line 12 within the options-medialibrary-uploader.php file.

        original code is:
        $of_page= 'appearance_page_options-framework';

        change it to
        $of_page= 'toplevel_page_options-framework';

        this should get your Uploader to work again.


  8. Hi Devin,
    How can I save all the present options?
    If I using a theme which has a lot options, and I have saved all the options,
    when I changed to a new server, I need to re-set the options, some times it may take a lot of time, I just want to know if it possible download all the options on the previous site?

  9. Hi Devin, thanks for an awesome plugin. This works so much better than the hand rolled options panel I had been working with in the past.

    Quick question, is it possible to make a textarea box use the TinyMCE visual editor?

    Thanks again,

    1. It’s always been difficult to have multiple instances of TinyMCE in the past, but WordPress 3.3 is supposed to have much better support for it. It could be a feature I roll out at some point if enough people request it.

  10. thanks alot.
    this is awesome.
    a little to strict in text area, maybe in next release another type of text area? with script and iframe, embed, etc as whitelist?

    or better, add it in array, so user can define their own validation/sanitize,

    (i know i can override it or just edit it directly, it’s just an idea)

    another idea is to add real metabox in admin panel, (i’m not sure it’s possible with your admin panel (i think at least it need real separete page for each page)

    and why background option? it’s not really needed, because wordpress already have one.

  11. Is there a way I can change the background image based on the page ID?

    So each individual post or page can have a different background image?

  12. Hello, Panel option is is very well congratulations, but I do not just insert the javascript adsense code disappears in the textarea.
    you know why?
    thank you

      1. You can add these code in the function.php

        add_action('admin_init','optionscheck_change_santiziation', 100);

        function optionscheck_change_santiziation() {
        remove_filter( 'of_sanitize_textarea', 'of_sanitize_textarea' );
        add_filter( 'of_sanitize_textarea', 'of_sanitize_textarea_custom' );

        function of_sanitize_textarea_custom($input) {
        global $allowedtags;
        $of_custom_allowedtags["embed"] = array(
        "src" => array(),
        "type" => array(),
        "allowfullscreen" => array(),
        "allowscriptaccess" => array(),
        "height" => array(),
        "width" => array()
        $of_custom_allowedtags["script"] = array(
        "src" => array(),
        "type" => array(),


        $of_custom_allowedtags = array_merge($of_custom_allowedtags, $allowedtags);
        $output = wp_kses( $input, $of_custom_allowedtags);
        return $output;

  13. Hi Devin,
    I was doing some digging inside options-medialibrary-uploader.php and was wondering if there was a specific reason for setting ‘can_export’ to true when the image uploader is setup as a custom post type. It makes the Options Framework Internal Container available via the standard WordPress editor and thought it might be a little confusing to see in that area. I implemented that ‘Import/Backup’ fork of the Options Theme (with a few tweaks to make it work) and that seems to do an awesome job (in case you are teetering on including it or not). Thanks!

  14. add_action('admin_init','optionscheck_change_santiziation', 100);

    function optionscheck_change_santiziation() {
    remove_filter( 'of_sanitize_textarea', 'of_sanitize_textarea' );
    add_filter( 'of_sanitize_textarea', 'of_sanitize_textarea_custom' );

    function of_sanitize_textarea_custom($input) {
    global $allowedtags;
    $of_custom_allowedtags["embed"] = array(
    "src" => array(),
    "type" => array(),
    "allowfullscreen" => array(),
    "allowscriptaccess" => array(),
    "height" => array(),
    "width" => array()
    $of_custom_allowedtags["script"] = array(
    "src" => array(),
    "type" => array(),


    $of_custom_allowedtags = array_merge($of_custom_allowedtags, $allowedtags);
    $output = wp_kses( $input, $of_custom_allowedtags);
    return $output;

  15. Hello there,

    I’m a front end web designer, not so familiar with php, however it seems I can figure my way around creating a wp theme with options page along with the assistance of your wonderful framework. I’m excited, but a little confused. If I want to make a theme that a user can use without having to download or activate any plutonium… Like to make a commercial theme I could sell…should I work with the options page theme? Or the options page plugin?

    1. There were a lot of updates in terms of data sanitization. If you want the older visual style I’d encourage you just to restyle the current version to how you’d like it.

      1. Im figuring it out now. Is the following still valid? They work, just want it to be stable. Thanks for the framework!

        // Pull all the categories into an array
        $options_categories = array();
        $options_categories_obj = get_categories();
        foreach ($options_categories_obj as $category) {
        $options_categories[$category->cat_ID] = $category->cat_name;

        // Pull all the pages into an array
        $options_pages = array();
        $options_pages_obj = get_pages(‘sort_column=post_parent,menu_order’);
        $options_pages[”] = ‘Select a page:’;
        foreach ($options_pages_obj as $page) {
        $options_pages[$page->ID] = $page->post_title;

      2. One last question, how can I make it so it can save google analytics code?
        Original code was:

        function childtheme_analytics(){
        $shortname = get_option(‘of_shortname’);
        $output = get_option($shortname . ‘_google_analytics’);
        if ( $output <> “” )
        echo stripslashes($output) . “\n”;

        The latest version doesn’t stipslash the javascript code.
        Thanks again.

    2. You can add these code in the function.php

      add_action('admin_init','optionscheck_change_santiziation', 100);

      function optionscheck_change_santiziation() {
      remove_filter( 'of_sanitize_textarea', 'of_sanitize_textarea' );
      add_filter( 'of_sanitize_textarea', 'of_sanitize_textarea_custom' );

      function of_sanitize_textarea_custom($input) {
      global $allowedtags;
      $of_custom_allowedtags["embed"] = array(
      "src" => array(),
      "type" => array(),
      "allowfullscreen" => array(),
      "allowscriptaccess" => array(),
      "height" => array(),
      "width" => array()
      $of_custom_allowedtags["script"] = array(
      "src" => array(),
      "type" => array(),


      $of_custom_allowedtags = array_merge($of_custom_allowedtags, $allowedtags);
      $output = wp_kses( $input, $of_custom_allowedtags);
      return $output;

  16. Hi Devin, thanks for your amazing framework.
    I try to change $of_page = add_theme_page(‘…’) to $of_page = add_menu_page(‘…’), everything seems OK except the uploader. It won’t work with add_menu_page function. Is it ok to change that function and can you tell me what possibly gone wrong ??

    Just trying to learn more about WP here.. :)
    Many thanks..

      1. @Yulius Edit the file options-medialibrary-uploader.php and replace ‘appearance_page_options-framework’ with ‘toplevel_page_options-framework’

      1. thanks for link, helped me a little.. but at the end i used that java you wrote from framework.. thanks.. ;D

        i have another question.. its about tinymce.. i managed to import it into framework, but it puts above everything else, above tabs. ofc i want it to show where it should. i used the_editor function for it.
        my question is do u know way how to do it? the_editor function echo’s everything and this framework puts everything in variable and later print it.. is there a way to include it inside variable? i tried to change the_edit into variable and then return it but couldn’t do it…

        i’ll be waiting for your answer. thanks

  17. Hey Devin,
    Just came across something that might be useful to others – I noticed the default list_pages and categories only displays a flat-list – but I’m having trouble getting the hierarchy to work correctly even after looking at the codex on this one. Any help you could provide on making that work? I think it’d be useful, especially for a site that has quite a few pages. Thanks!

  18. Hi – trying to implement the code above for allowing adsense/analytics (added to functions.php).

    When I add the analytics code to the textarea in the options page it displays the tags but doesn’t show anything in between. i.e


    Any ideas where I’m going wrong?

  19. Thanks Devin.

    I had to change:

    $custom_allowedtags["script"] = array();


    $custom_allowedtags["script"] = array("src" => array());

    to include the last part of the Adsense code.

  20. Hi Devin,
    Thank you very much for sharing this great script.

    I was trying to add an extra subpage to the options menu, I tried with the add_submenu_page function but instead of adding a new link it changed the first one on the list…

    Could you please help me with the correct function?

  21. Hello! Thanks for the great work.
    With the release of WP 3.3, it appears that the media upload functionality of your theme options framework is broken :( I just wanted to give you a quick heads up, and ask if you have considered a fix?

    Thanks again Devin!

    1. sorry, it’s working well, the one not working is vauvarin version with export -import feature. nothing happen when i click upload button or delete image button.

  22. How do you create an if statement for when a certain select is selected. I need a select input so I can load a different CSS file for each different option selected. I can’t seem to work it out from the included examples.

    Thanks for the theme!

  23. Hi Devin, I’m sorry to bother you, but after multiple hard browser refresh the image uploader is still dead.
    Tried with Safari, FF8, and Chrome
    Any Idea?


      1. Hi Devin, Thank you very much for your quick reply.
        No, I’m not getting any errors, I tried setting up a VM with virtualbox and I tested with IE and, unfortunately, the issue remains.

        The strange things is that the uploader in the custom meta is working, I can’t figure it out…

    1. if you changed “options-framework”(160 line) in options-framework.php
      $of_page = add_theme_page('Theme Options', 'Theme Options', 'edit_theme_options', 'options-framework','optionsframework_page');
      you have to change
      $of_page= 'appearance_page_options-framework';
      in options-medialibrary-uploader.php (line 12) as well

      in one case this worked for me…

  24. Hi!

    I changed “options-framework”(160 line) in options-framework.php from
    $of_page = add_theme_page(‘Theme Options’, ‘Theme Options’, ‘edit_theme_options’, ‘options-framework’,’optionsframework_page’);
    $of_page = add_menu_page(‘Theme Options’, ‘Theme Options’, ‘edit_theme_options’, ‘options-framework’,’optionsframework_page’);

    and upload doesen’t work, I dont now what i must change in options-medialibrary-uploader.php on line 12
    $of_page= ‘appearance_page_options-framework’;

  25. Love this framework. Great work!

    I’m stuck with calling the multicheck selections for use. I’ve created an array of categories using:

    $options_categories = array();
    $options_categories_obj = get_categories();
    foreach ($options_categories_obj as $category) {
    $options_categories[$category->cat_ID] = $category->cat_name;

    Now I’m looking to get the selected categories (name or id) separated with commas to use in a function with no luck.

    Clue for the clueless? Thanks.

  26. thanks…I am not really understand this..Caused my poor English…
    Can I add a button to delete a file….
    We upload a file from the option page (like logo、banner),we also need to delete it…
    forgive my poor English

    1. You should be able to remove an image from the field. That won’t delete it from the filesystem entirely though. You’d need to go into the Media section in order to do that.

  27. Greetings,

    Love your options panel plugin. I’d like to adapt it to show as a top-level link in the left column of the WordPress admin rather than as a submenu part of the Appearance panel.

    My efforts included revising the function optionsframework_add_page().
    On about line 235, rather than using add_theme_page(), I did this:
    $of_page = add_menu_page('Theme Options', 'ATG Options', 'edit_theme_options', 'options-framework','optionsframework_page',WP_PLUGIN_URL.'/options-framework-plugin/images/icon.png','05');

    However, that seemed to break the Image Uploading function.
    Any suggestions are greatly appreciated.
    Thanks! And thanks for the great work on this plugin/theme.

    1. This question has come up several times in the comments. I finally updated the post with that information, though I highly recommended leaving theme options under the “Appearance” menu.

  28. Thanks so much, Devin.
    I appreciate your work and your advice.
    I’m using the panel not as Theme Options, per se. But rather for the client to input some specific data.
    Therefore, the Appearance tab doesn’t quite seem appropriate for this particular case.
    Thx again.

  29. Hi,

    How would I go about creating a duplicate of the uploader function, that won’t resize images? I use the regular background/upload to create various sizes of images, to use in various medias – but I need a separate one for a background that only uses the originally uploaded file, and creating various sizes then wastes space for files that won’t be used.

    I may have explained it better here:

    Any help would be appreciated!

      1. Hi again,

        I conjured up a solution, but can’t get it to save the data from it. Any suggestions on what may be wrong? Here is what I did…

        It does work as expected (with some added CSS), and does infact upload the selected image singularely – but when clicking “Save Options” at the bottom, the values in the two fields are not saved in the database.

      2. The sanitizing was harder than I thought; it works for everything except the actual image-url, which I tried sanitizing with add_filter( ‘of_sanitize_background_no_resize’, ‘of_sanitize_background’ ); – but it does not save.

        Looking at options-sanitize.php it appears that of_sanitize_background refers to of_sanitize_upload, which checks the extension of the file (tested with .jpg). I can’t seem to find out where the error is; is there a debug mode or similar?

  30. hello Devin.. it’s me again xD

    i have one question, i didnt made any modification to the code, and “std” is set for every options, but when i click that button, every value on every field becomes “a”… do u know what this could be?

  31. Possible bug: I have noticed when using the theme options framework with my themes… if I rename the primary theme folder, the theme will break. My quick fix: remove the theme options admin folder and paste it back in. Obviously, back up any changes you might have made before doing this.

    1. If you didn’t specifically set the option name to use it will build one based off the theme name. If you want someone to be able to change the theme name and keep their options the same, you should set the id in optionsframework_option_name, inside options.php.

  32. Quick update – tested on non-multisite instead with Headway theme and it works. So I’m guessing there is a multisite issue?

    Also, could someone give a quick example of changing the id in the options.php? I do need my users to be able to keep the options set even if the theme changes.

    Thanks in advance!

    1. On multisite, it is also not saving into the specific blogs option table, but saving into the main blog wp_options instead.

      Is there a fix for the multisite issues with the theme version? Otherwise, I’ll have to try the plugin version to see if that works.

      1. Hi Devin,

        Thanks so much – I found everything and I’m proceeding forward. I did a complete fresh install of my headway framework and the options framework – and everything is working correctly in multisite.

        Not sure what happened the first time, but it’s definitely not a problem on your side.

        Thanks again for this wonderful framework!

  33. Sorry, one last question. I’m trying to override the 32×32 image pulled from the default Appearance menus – as I’m using this custom options panel for some specific information. Could you tell me where I could change the code that’s generating the with the default id and class so I can bypass the image with my own?

  34. Finally, I can turn the textarea to TinyMCE Editor…. YEEEEEY…
    that’s really help me to get more variation while editing the text…

    if you want the script, just contact me or replay this message… :)

      1. actually I know you can and you don’t need to get the script from me, because you’re a master… :D
        I just wanna share the code to anyone who need tinyMCE editor to the textarea.

        And we hope you will release a new version of Option framework.

  35. Hi Devin,
    I’ve create my options, but haven’t a bit of a problem with the main heading tabs. Whenever I first activate the theme, the options tabs will default to my 2nd tab being active instead of the 1st tab. It remembers what I’ve selected, so the next time it goes to whatever tab I was on.

    How can I ensure the 1st tab is active on theme activation?

    1. It uses local storage to store which tab is active. See options-custom.js: localStorage.getItem(“activetab”). It should default to the first tab if that variable isn’t set- so perhaps your browser is still reading that variable. Try it in a different browser or clear all your cache data.

  36. Hi Devin,

    Have you thought about, or can you recommend, a way to integrate Tool Tips into the options framework? I trying to “client-proof” my options panel, and I would kill for the ability to have a ? after a label that’s linked to a tool tip.

    Any recommendations?

Leave a Reply

Your email address will not be published. Required fields are marked *