Ghost not showing all Menu Items


I am trying to build my website on ghost (using casper) but ghost is not displaying all the menu items. instead it is showing 3 dots.

Is there a way I can fix that?

Hey Lucas!

Casper adds this “more” toggle (the three dots) when the navigation is too wide for the screen size.

Usually, this shouldn’t be a problem. Here is a quick sample I pulled up:

Just a wild guess: it looks like you’ve implemented a dropdown menu. Depending on where and how this dropdown functionality is called in the theme, it might be after the theme checks whether the navigation items are too wide.

So, the theme then cuts them off, since the “dropdown-ification” only happens afterwards.

If you’ve applied any customisations to your theme, post them here and we can help more.

Thank you for the fast reply.

I added this to the header:


/* For Dropdown Menus */ {
    position: relative;
    padding-right: 25px!important;
    display: inline;
} ul.ghost-submenu {
    visibility: visible!important;
    opacity: 1!important;
    top: 30px!important;

.menu-item-has-children svg {
    position: absolute;
    right: 0px;
    top: 60%;
    transform: translate(-0%, -50%) scale(1.1);

ul.ghost-submenu li {
    list-style: none;
    white-space: nowrap;

ul.ghost-submenu {
    border-radius: 5px;
    position: absolute;
    visibility: hidden;
    z-index: 1;
    opacity: 0;
    top: 30px;
    transition: 0.3s;
    box-shadow: 0 1px 5px 0 rgb(0 0 0 / 14%);
    max-width: unset !important;
    /* Edit below to adjust Dropdown Menu positioning and color */
    left: 0;
    margin-top: -0px;
    padding: 5px 20px 10px 10px;
    background: #fff;
    color: #000;


And this to the footer:

Thank you very much!

Footer got lost:

// For Dropdown Menu
(function($) {
    "use strict";
    function ghost_dropdown(options) {
       let defultOptions = {
            targetElement: "ul li",
            hasChildrenClasses: "menu-item-has-children",
            hasChildrenIcon: "<svg xmlns='' width='11' height='7' fill='currentColor' class='bi bi-caret-down' viewBox='0 0 11 7'><path d='M5.4999 6.20003L0.649902 1.35003L1.3499 0.650024L5.4999 4.80002L9.6499 0.650024L10.3499 1.35003L5.4999 6.20003Z'/></svg>",
            hasChildDetectText: "[has_child]",
            submenuUlClasses: "ghost-submenu",
            subitemDetectText: "[subitem]",
            subitemLiClasses: "subitem"
        options = {
        // Target Element
        let targetElement = options.targetElement;
        //Default value 
        let hasChildrenClasses = options.hasChildrenClasses;
        let hasChildrenIcon = options.hasChildrenIcon;
        let hasChildDetectText = options.hasChildDetectText;
        let submenuUlClasses = options.submenuUlClasses;
        let subitemDetectText = options.subitemDetectText;
        let subitemLiClasses = options.subitemLiClasses;
        // Declare neccesary variable
        let parentEl = $(targetElement);
        let childEL = $(targetElement);
        let parentLen = 0;
        let domArrayElement = [];
        let indexPush = [];
        let elIndex = 0;
        let parentIndex = [];
        // Find Dropdown parent element
        parentEl.each(function(index, element) {
            if ($(this).text().indexOf(hasChildDetectText) >= 0) {
                parentIndex.push(index); // Make dropdown parent array index
                $(this).addClass(hasChildrenClasses); // Add class in dropdown element
                $(this).append(`<ul class='${submenuUlClasses}'></ul>`); // Append submenu element
                $(targetElement).css("opacity", "1");
        // Using loop to reach dropdown parent element
        for (let i = 0; i < parentLen; i++) {
            elIndex = 0 // Initial element value
            // Find subitem element
            childEL.each(function(index, element) {
                let subitem = $(this).text().includes(subitemDetectText); // Find subitem element
                if (subitem) {
                    if (elIndex >= parentIndex[i + 1]) { // Each loop will be break
                        return false; //Stoped each loop 
                    if (elIndex <= parentIndex[i + 1] || elIndex >= parentIndex[parentIndex.length - 1]) {
                        if (!indexPush.includes(index)) { //Check if not index already insert 
                            $(this).addClass(subitemLiClasses); // Add class in subitem element
                            let st = $(this).children().text(); // Find subitem inner text
                            $(this).children().text(st.replaceAll(subitemDetectText, "")); // Replace subitem inner text
                            domArrayElement.push(element); // Incert subitem element in dom array
                            indexPush.push(index); // incert subitem index in indexPush array
                elIndex++; // increase element index value
            $(`.${hasChildrenClasses} ul.${submenuUlClasses}:eq(${i})`).append(domArrayElement); // Append related subitem dom element into submenu 
            // console.log(domArrayElement);
            domArrayElement = []; // Make dom array element empty. 
        const hasChildEl = $(`.${hasChildrenClasses}`);
        hasChildEl.each(function() {
            if ($(this).find("> a:first").text().includes(hasChildDetectText)) {
                console.log($(this).find("> a").text());
                let hasChildText = $(this).find("> a:first").text(); // Find has child inner text
                $(this).find("> a:first").text(hasChildText.replaceAll(hasChildDetectText, ""));
    $(document).ready(function() {

I just played around a bit with the dropdown you implemented (GitHub - akashmdiu/ghost-dynamic-dropdown).

Given the logic the Casper theme has, I don’t really see a way for these two to work together, when you have a big drop-down menu.

The makeDropdown function of the Casper theme (responsible for creating the three dots) will run on multiple occasions: when the page loads (specifically after the images are loaded) AND when a window is resized. The dropdown “plugin” you implemented only runs once (on page load). So, whenever a visitor resizes their browser window, the dropdown effectively gets destroyed.

I also tried to change the way the individual JS files get loaded, but they are effectively “cancelling” each other out.

The only way I got this working was to remove the makeDropdown function and its implementations from the dropdown.js I linked above.

Then the theme looks like this:

However, this does not fix the issue I mentioned above: on window resize the dropdown “plugin” breaks. The visitor will only see the navigation again once the page is reloaded.

Thank you very much!

I’ve been doing my own exploring on this same topic and it looks from your website like you were able to resolve the issue. Did you end up just manually removing the makeDropdown function from dropdown.js to get it to work?

Lucas and I ended up working together and he hired me for the theme customisation. It was quite a bit more than just the drop-down, though, and we ended up going for a pretty customised version of the navigation.