Skip to content

Instantly share code, notes, and snippets.

@simonw

simonw/nav.md Secret

Created October 20, 2024 12:25
Show Gist options
  • Save simonw/53648554917862676ccd12dcf5cc9cab to your computer and use it in GitHub Desktop.
Save simonw/53648554917862676ccd12dcf5cc9cab to your computer and use it in GitHub Desktop.

Horizontal Navigation Bar with Text Wrap Toggle

human (Oct 20, 2024, 05:05 AM)

Build an artifact - no react - that demonstrates a navigation bar with 8 items in it laid out horizontally - then add a checkbox which toggles the CSS rule text-wrap: balance for that nav bar

assistant (Oct 20, 2024, 05:05 AM)

Certainly! I'll create an HTML artifact that demonstrates a navigation bar with 8 items laid out horizontally, along with a checkbox to toggle the text-wrap: balance CSS rule for the navigation bar.

Navigation Bar with Text-Wrap Toggle

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Navigation Bar with Text-Wrap Toggle</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
        }
        nav {
            background-color: #f0f0f0;
            padding: 10px;
            margin-bottom: 20px;
        }
        ul {
            list-style-type: none;
            padding: 0;
            margin: 0;
            display: flex;
            flex-wrap: wrap;
        }
        li {
            margin-right: 10px;
            margin-bottom: 5px;
        }
        a {
            text-decoration: none;
            color: #333;
            padding: 5px 10px;
            border-radius: 3px;
            background-color: #e0e0e0;
        }
        .checkbox-container {
            margin-top: 20px;
        }
    </style>
</head>
<body>
    <nav id="main-nav">
        <ul>
            <li><a href="#">Home</a></li>
            <li><a href="#">About</a></li>
            <li><a href="#">Services</a></li>
            <li><a href="#">Products</a></li>
            <li><a href="#">Blog</a></li>
            <li><a href="#">Contact</a></li>
            <li><a href="#">FAQ</a></li>
            <li><a href="#">Support</a></li>
        </ul>
    </nav>

    <div class="checkbox-container">
        <label>
            <input type="checkbox" id="balance-toggle"> Enable text-wrap: balance
        </label>
    </div>

    <script>
        const nav = document.getElementById('main-nav');
        const toggle = document.getElementById('balance-toggle');

        toggle.addEventListener('change', function() {
            if (this.checked) {
                nav.style.textWrap = 'balance';
            } else {
                nav.style.textWrap = 'wrap';
            }
        });
    </script>
</body>
</html>

This HTML artifact demonstrates a navigation bar with 8 items laid out horizontally. It also includes a checkbox that toggles the text-wrap: balance CSS rule for the navigation bar. Here's a breakdown of the key components:

  1. The navigation bar is created using an unordered list (<ul>) with 8 list items (<li>), each containing a link (<a>).
  2. The CSS styles the navigation bar horizontally using display: flex and flex-wrap: wrap.
  3. A checkbox is added below the navigation bar to toggle the text-wrap property.
  4. JavaScript is used to listen for changes to the checkbox and apply or remove the text-wrap: balance style accordingly.

You can copy this code and save it as an HTML file to see it in action. The text-wrap: balance property is a relatively new CSS feature, so it may not be supported in all browsers. In browsers that don't support it, the layout will fall back to the default wrapping behavior.

Would you like me to explain any part of the code in more detail?

human (Oct 20, 2024, 05:06 AM)

Increase to 12 nav items and add margin-bottom to them

assistant (Oct 20, 2024, 05:06 AM)

Certainly! I'll update the artifact to include 12 navigation items instead of 8, and add a margin-bottom to the navigation items.

Navigation Bar with Text-Wrap Toggle (12 items)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Navigation Bar with Text-Wrap Toggle</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
        }
        nav {
            background-color: #f0f0f0;
            padding: 10px;
            margin-bottom: 20px;
        }
        ul {
            list-style-type: none;
            padding: 0;
            margin: 0;
            display: flex;
            flex-wrap: wrap;
        }
        li {
            margin-right: 10px;
            margin-bottom: 10px; /* Added margin-bottom */
        }
        a {
            text-decoration: none;
            color: #333;
            padding: 5px 10px;
            border-radius: 3px;
            background-color: #e0e0e0;
        }
        .checkbox-container {
            margin-top: 20px;
        }
    </style>
</head>
<body>
    <nav id="main-nav">
        <ul>
            <li><a href="#">Home</a></li>
            <li><a href="#">About</a></li>
            <li><a href="#">Services</a></li>
            <li><a href="#">Products</a></li>
            <li><a href="#">Blog</a></li>
            <li><a href="#">Contact</a></li>
            <li><a href="#">FAQ</a></li>
            <li><a href="#">Support</a></li>
            <li><a href="#">Portfolio</a></li>
            <li><a href="#">Team</a></li>
            <li><a href="#">Careers</a></li>
            <li><a href="#">Partners</a></li>
        </ul>
    </nav>

    <div class="checkbox-container">
        <label>
            <input type="checkbox" id="balance-toggle"> Enable text-wrap: balance
        </label>
    </div>

    <script>
        const nav = document.getElementById('main-nav');
        const toggle = document.getElementById('balance-toggle');

        toggle.addEventListener('change', function() {
            if (this.checked) {
                nav.style.textWrap = 'balance';
            } else {
                nav.style.textWrap = 'wrap';
            }
        });
    </script>
</body>
</html>

I've made the following changes to the artifact:

  1. Increased the number of navigation items from 8 to 12 by adding four new items: "Portfolio", "Team", "Careers", and "Partners".

  2. Added a margin-bottom: 10px; to the li elements in the CSS. This will create some vertical space between the navigation items when they wrap to a new line.

The rest of the code remains the same, including the functionality to toggle the text-wrap: balance property.

These changes will make the navigation bar more comprehensive and improve its appearance when the items wrap to multiple lines. The additional margin-bottom will help distinguish between rows of navigation items, making it easier to read and navigate.

Would you like me to explain any part of the updated code or make any further modifications?

human (Oct 20, 2024, 05:07 AM)

Have a range slider for the number of visible navigation items from 4 to 14 - and make that bottom margin a bit bigger

assistant (Oct 20, 2024, 05:07 AM)

Certainly! I'll update the artifact to include a range slider that controls the number of visible navigation items, and I'll increase the bottom margin for the navigation items.

Navigation Bar with Text-Wrap Toggle and Item Count Slider

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Navigation Bar with Text-Wrap Toggle and Item Count Slider</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
        }
        nav {
            background-color: #f0f0f0;
            padding: 10px;
            margin-bottom: 20px;
        }
        ul {
            list-style-type: none;
            padding: 0;
            margin: 0;
            display: flex;
            flex-wrap: wrap;
        }
        li {
            margin-right: 10px;
            margin-bottom: 15px; /* Increased bottom margin */
        }
        a {
            text-decoration: none;
            color: #333;
            padding: 5px 10px;
            border-radius: 3px;
            background-color: #e0e0e0;
        }
        .controls {
            margin-top: 20px;
        }
        .control-item {
            margin-bottom: 10px;
        }
        #item-count-value {
            margin-left: 10px;
        }
    </style>
</head>
<body>
    <nav id="main-nav">
        <ul>
            <li><a href="#">Home</a></li>
            <li><a href="#">About</a></li>
            <li><a href="#">Services</a></li>
            <li><a href="#">Products</a></li>
            <li><a href="#">Blog</a></li>
            <li><a href="#">Contact</a></li>
            <li><a href="#">FAQ</a></li>
            <li><a href="#">Support</a></li>
            <li><a href="#">Portfolio</a></li>
            <li><a href="#">Team</a></li>
            <li><a href="#">Careers</a></li>
            <li><a href="#">Partners</a></li>
            <li><a href="#">News</a></li>
            <li><a href="#">Events</a></li>
        </ul>
    </nav>

    <div class="controls">
        <div class="control-item">
            <label for="item-count">Number of visible items:</label>
            <input type="range" id="item-count" min="4" max="14" value="14">
            <span id="item-count-value">14</span>
        </div>
        <div class="control-item">
            <label>
                <input type="checkbox" id="balance-toggle"> Enable text-wrap: balance
            </label>
        </div>
    </div>

    <script>
        const nav = document.getElementById('main-nav');
        const toggle = document.getElementById('balance-toggle');
        const itemCountSlider = document.getElementById('item-count');
        const itemCountValue = document.getElementById('item-count-value');
        const navItems = nav.querySelectorAll('li');

        function updateVisibleItems(count) {
            navItems.forEach((item, index) => {
                item.style.display = index < count ? 'block' : 'none';
            });
        }

        toggle.addEventListener('change', function() {
            nav.style.textWrap = this.checked ? 'balance' : 'wrap';
        });

        itemCountSlider.addEventListener('input', function() {
            const count = parseInt(this.value);
            itemCountValue.textContent = count;
            updateVisibleItems(count);
        });

        // Initialize with all items visible
        updateVisibleItems(14);
    </script>
</body>
</html>

I've made the following changes to the artifact:

  1. Increased the bottom margin of navigation items from 10px to 15px for better spacing:

    li {
        margin-right: 10px;
        margin-bottom: 15px; /* Increased from 10px to 15px */
    }
  2. Added a range slider to control the number of visible navigation items:

    <div class="control-item">
        <label for="item-count">Number of visible items:</label>
        <input type="range" id="item-count" min="4" max="14" value="14">
        <span id="item-count-value">14</span>
    </div>
  3. Increased the total number of navigation items to 14 to match the maximum value of the slider.

  4. Added JavaScript to handle the slider functionality:

    const itemCountSlider = document.getElementById('item-count');
    const itemCountValue = document.getElementById('item-count-value');
    const navItems = nav.querySelectorAll('li');
    
    function updateVisibleItems(count) {
        navItems.forEach((item, index) => {
            item.style.display = index < count ? 'block' : 'none';
        });
    }
    
    itemCountSlider.addEventListener('input', function() {
        const count = parseInt(this.value);
        itemCountValue.textContent = count;
        updateVisibleItems(count);
    });
    
    // Initialize with all items visible
    updateVisibleItems(14);

These changes allow the user to dynamically adjust the number of visible navigation items using the slider, while also maintaining the text-wrap balance toggle functionality. The increased bottom margin provides better visual separation between rows of navigation items.

Would you like me to explain any part of the updated code or make any further modifications?

human (Oct 20, 2024, 05:08 AM)

Don't use flexbox at all, use inline block

assistant (Oct 20, 2024, 05:08 AM)

Certainly! I'll modify the CSS to use inline-block instead of flexbox for the navigation items. This will change how the items are laid out and wrapped.

Navigation Bar with Text-Wrap Toggle and Item Count Slider (using inline-block)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Navigation Bar with Text-Wrap Toggle and Item Count Slider (using inline-block)</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
        }
        nav {
            background-color: #f0f0f0;
            padding: 10px;
            margin-bottom: 20px;
        }
        ul {
            list-style-type: none;
            padding: 0;
            margin: 0;
        }
        li {
            display: inline-block;
            margin-right: 10px;
            margin-bottom: 15px;
        }
        a {
            text-decoration: none;
            color: #333;
            padding: 5px 10px;
            border-radius: 3px;
            background-color: #e0e0e0;
        }
        .controls {
            margin-top: 20px;
        }
        .control-item {
            margin-bottom: 10px;
        }
        #item-count-value {
            margin-left: 10px;
        }
    </style>
</head>
<body>
    <nav id="main-nav">
        <ul>
            <li><a href="#">Home</a></li>
            <li><a href="#">About</a></li>
            <li><a href="#">Services</a></li>
            <li><a href="#">Products</a></li>
            <li><a href="#">Blog</a></li>
            <li><a href="#">Contact</a></li>
            <li><a href="#">FAQ</a></li>
            <li><a href="#">Support</a></li>
            <li><a href="#">Portfolio</a></li>
            <li><a href="#">Team</a></li>
            <li><a href="#">Careers</a></li>
            <li><a href="#">Partners</a></li>
            <li><a href="#">News</a></li>
            <li><a href="#">Events</a></li>
        </ul>
    </nav>

    <div class="controls">
        <div class="control-item">
            <label for="item-count">Number of visible items:</label>
            <input type="range" id="item-count" min="4" max="14" value="14">
            <span id="item-count-value">14</span>
        </div>
        <div class="control-item">
            <label>
                <input type="checkbox" id="balance-toggle"> Enable text-wrap: balance
            </label>
        </div>
    </div>

    <script>
        const nav = document.getElementById('main-nav');
        const toggle = document.getElementById('balance-toggle');
        const itemCountSlider = document.getElementById('item-count');
        const itemCountValue = document.getElementById('item-count-value');
        const navItems = nav.querySelectorAll('li');

        function updateVisibleItems(count) {
            navItems.forEach((item, index) => {
                item.style.display = index < count ? 'inline-block' : 'none';
            });
        }

        toggle.addEventListener('change', function() {
            nav.style.textWrap = this.checked ? 'balance' : 'normal';
        });

        itemCountSlider.addEventListener('input', function() {
            const count = parseInt(this.value);
            itemCountValue.textContent = count;
            updateVisibleItems(count);
        });

        // Initialize with all items visible
        updateVisibleItems(14);
    </script>
</body>
</html>

Here are the key changes I've made to switch from flexbox to inline-block:

  1. Removed flexbox-related CSS from the ul selector:

    ul {
        list-style-type: none;
        padding: 0;
        margin: 0;
    }
  2. Changed the li elements to use inline-block:

    li {
        display: inline-block;
        margin-right: 10px;
        margin-bottom: 15px;
    }
  3. Updated the JavaScript updateVisibleItems function to use 'inline-block' instead of 'block':

    function updateVisibleItems(count) {
        navItems.forEach((item, index) => {
            item.style.display = index < count ? 'inline-block' : 'none';
        });
    }
  4. Changed the text-wrap property toggle to use 'normal' instead of 'wrap':

    toggle.addEventListener('change', function() {
        nav.style.textWrap = this.checked ? 'balance' : 'normal';
    });

These changes accomplish the following:

  • The navigation items now use inline-block for layout, which allows them to flow horizontally and wrap to the next line when needed, similar to how text behaves.
  • The margin-right and margin-bottom on the li elements provide spacing between items, both horizontally and vertically when they wrap.
  • The text-wrap: balance toggle now switches between 'balance' and 'normal', which is more appropriate for inline-block layout.

This layout will behave slightly differently from the flexbox version, particularly in how it wraps and distributes space. The inline-block approach may leave more uneven space at the end of lines, but it closely mimics traditional text layout.

Would you like me to explain any part of these changes in more detail or make any further modifications?

human (Oct 20, 2024, 05:10 AM)

Unchecking it doesn't seem to undo the effect

assistant (Oct 20, 2024, 05:10 AM)

You're right, and I apologize for that oversight. Let's fix the issue so that unchecking the box properly undoes the text-wrap: balance effect. We'll need to modify the JavaScript to handle this correctly.

Navigation Bar with Text-Wrap Toggle and Item Count Slider (using inline-block)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Navigation Bar with Text-Wrap Toggle and Item Count Slider (using inline-block)</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
        }
        nav {
            background-color: #f0f0f0;
            padding: 10px;
            margin-bottom: 20px;
        }
        ul {
            list-style-type: none;
            padding: 0;
            margin: 0;
        }
        li {
            display: inline-block;
            margin-right: 10px;
            margin-bottom: 15px;
        }
        a {
            text-decoration: none;
            color: #333;
            padding: 5px 10px;
            border-radius: 3px;
            background-color: #e0e0e0;
        }
        .controls {
            margin-top: 20px;
        }
        .control-item {
            margin-bottom: 10px;
        }
        #item-count-value {
            margin-left: 10px;
        }
    </style>
</head>
<body>
    <nav id="main-nav">
        <ul>
            <li><a href="#">Home</a></li>
            <li><a href="#">About</a></li>
            <li><a href="#">Services</a></li>
            <li><a href="#">Products</a></li>
            <li><a href="#">Blog</a></li>
            <li><a href="#">Contact</a></li>
            <li><a href="#">FAQ</a></li>
            <li><a href="#">Support</a></li>
            <li><a href="#">Portfolio</a></li>
            <li><a href="#">Team</a></li>
            <li><a href="#">Careers</a></li>
            <li><a href="#">Partners</a></li>
            <li><a href="#">News</a></li>
            <li><a href="#">Events</a></li>
        </ul>
    </nav>

    <div class="controls">
        <div class="control-item">
            <label for="item-count">Number of visible items:</label>
            <input type="range" id="item-count" min="4" max="14" value="14">
            <span id="item-count-value">14</span>
        </div>
        <div class="control-item">
            <label>
                <input type="checkbox" id="balance-toggle"> Enable text-wrap: balance
            </label>
        </div>
    </div>

    <script>
        const nav = document.getElementById('main-nav');
        const toggle = document.getElementById('balance-toggle');
        const itemCountSlider = document.getElementById('item-count');
        const itemCountValue = document.getElementById('item-count-value');
        const navItems = nav.querySelectorAll('li');

        function updateVisibleItems(count) {
            navItems.forEach((item, index) => {
                item.style.display = index < count ? 'inline-block' : 'none';
            });
        }

        function updateTextWrap() {
            if (toggle.checked) {
                nav.style.textWrap = 'balance';
            } else {
                nav.style.textWrap = '';  // Remove the property entirely
            }
        }

        toggle.addEventListener('change', updateTextWrap);

        itemCountSlider.addEventListener('input', function() {
            const count = parseInt(this.value);
            itemCountValue.textContent = count;
            updateVisibleItems(count);
        });

        // Initialize with all items visible and default text-wrap
        updateVisibleItems(14);
        updateTextWrap();
    </script>
</body>
</html>

I've made the following changes to fix the issue with the text-wrap toggle:

  1. Created a new updateTextWrap function:

    function updateTextWrap() {
        if (toggle.checked) {
            nav.style.textWrap = 'balance';
        } else {
            nav.style.textWrap = '';  // Remove the property entirely
        }
    }

    This function now properly handles both the checked and unchecked states. When unchecked, it removes the text-wrap property entirely, allowing the browser to use its default text wrapping behavior.

  2. Updated the event listener for the toggle:

    toggle.addEventListener('change', updateTextWrap);

    Now it calls our new updateTextWrap function directly.

  3. Added an initial call to updateTextWrap() at the end of the script to ensure the correct initial state.

These changes ensure that:

  • When the checkbox is checked, text-wrap: balance is applied.
  • When the checkbox is unchecked, the text-wrap property is removed entirely, reverting to the browser's default behavior.
  • The initial state is correctly set based on the checkbox's initial state.

Now, toggling the checkbox should correctly apply and remove the text-wrap: balance effect. The navigation items will use the balanced wrapping when the box is checked, and revert to normal wrapping behavior when unchecked.

This solution provides a clear demonstration of the difference between balanced and normal text wrapping for the navigation items. Users can now easily compare the two wrapping behaviors by toggling the checkbox.

Is there anything else you'd like me to adjust or explain about this update?

human (Oct 20, 2024, 05:12 AM)

Set the width on the display area of the navigation menu to be fixed at 600px

assistant (Oct 20, 2024, 05:12 AM)

Certainly! I'll modify the CSS to set a fixed width of 600px for the navigation menu's display area. This will help demonstrate the text wrapping behavior more clearly within a constrained space.

Navigation Bar with Text-Wrap Toggle and Item Count Slider (600px width)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Navigation Bar with Text-Wrap Toggle and Item Count Slider (600px width)</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
        }
        nav {
            background-color: #f0f0f0;
            padding: 10px;
            margin-bottom: 20px;
            width: 600px; /* Set fixed width for nav area */
            box-sizing: border-box; /* Include padding in width calculation */
        }
        ul {
            list-style-type: none;
            padding: 0;
            margin: 0;
        }
        li {
            display: inline-block;
            margin-right: 10px;
            margin-bottom: 15px;
        }
        a {
            text-decoration: none;
            color: #333;
            padding: 5px 10px;
            border-radius: 3px;
            background-color: #e0e0e0;
        }
        .controls {
            margin-top: 20px;
            width: 600px; /* Match width of nav for alignment */
        }
        .control-item {
            margin-bottom: 10px;
        }
        #item-count-value {
            margin-left: 10px;
        }
    </style>
</head>
<body>
    <nav id="main-nav">
        <ul>
            <li><a href="#">Home</a></li>
            <li><a href="#">About</a></li>
            <li><a href="#">Services</a></li>
            <li><a href="#">Products</a></li>
            <li><a href="#">Blog</a></li>
            <li><a href="#">Contact</a></li>
            <li><a href="#">FAQ</a></li>
            <li><a href="#">Support</a></li>
            <li><a href="#">Portfolio</a></li>
            <li><a href="#">Team</a></li>
            <li><a href="#">Careers</a></li>
            <li><a href="#">Partners</a></li>
            <li><a href="#">News</a></li>
            <li><a href="#">Events</a></li>
        </ul>
    </nav>

    <div class="controls">
        <div class="control-item">
            <label for="item-count">Number of visible items:</label>
            <input type="range" id="item-count" min="4" max="14" value="14">
            <span id="item-count-value">14</span>
        </div>
        <div class="control-item">
            <label>
                <input type="checkbox" id="balance-toggle"> Enable text-wrap: balance
            </label>
        </div>
    </div>

    <script>
        const nav = document.getElementById('main-nav');
        const toggle = document.getElementById('balance-toggle');
        const itemCountSlider = document.getElementById('item-count');
        const itemCountValue = document.getElementById('item-count-value');
        const navItems = nav.querySelectorAll('li');

        function updateVisibleItems(count) {
            navItems.forEach((item, index) => {
                item.style.display = index < count ? 'inline-block' : 'none';
            });
        }

        function updateTextWrap() {
            if (toggle.checked) {
                nav.style.textWrap = 'balance';
            } else {
                nav.style.textWrap = '';  // Remove the property entirely
            }
        }

        toggle.addEventListener('change', updateTextWrap);

        itemCountSlider.addEventListener('input', function() {
            const count = parseInt(this.value);
            itemCountValue.textContent = count;
            updateVisibleItems(count);
        });

        // Initialize with all items visible and default text-wrap
        updateVisibleItems(14);
        updateTextWrap();
    </script>
</body>
</html>

Here are the key changes I've made to set a fixed width for the navigation menu:

  1. Added a fixed width to the nav element:

    nav {
        background-color: #f0f0f0;
        padding: 10px;
        margin-bottom: 20px;
        width: 600px; /* Set fixed width for nav area */
        box-sizing: border-box; /* Include padding in width calculation */
    }

    This sets the navigation area to a fixed width of 600px. The box-sizing: border-box ensures that the padding is included within this width.

  2. Adjusted the .controls container to match the width of the navigation area:

    .controls {
        margin-top: 20px;
        width: 600px; /* Match width of nav for alignment */
    }

    This keeps the controls aligned with the navigation area for a cleaner look.

These changes will make the following improvements to the demo:

  1. The navigation menu now has a fixed width of 600px, which will clearly demonstrate how the menu items wrap within a constrained space.
  2. The difference between balanced and normal text wrapping will be more noticeable, especially when toggling the "Enable text-wrap: balance" checkbox.
  3. The fixed width provides a consistent layout for testing different numbers of menu items and observing how they wrap.

This update enhances the demonstration of text wrapping behaviors in a more realistic scenario, where navigation menus often have width constraints. Users can now more easily observe how the text-wrap: balance property affects the layout of menu items within this fixed width.

Is there anything else you'd like me to adjust or explain about this update?

human (Oct 20, 2024, 05:12 AM)

Drop that to 400px

assistant (Oct 20, 2024, 05:12 AM)

Certainly! I'll adjust the width of the navigation area to 400px. This will create an even more constrained space, making the wrapping behavior more pronounced.

Navigation Bar with Text-Wrap Toggle and Item Count Slider (400px width)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Navigation Bar with Text-Wrap Toggle and Item Count Slider (400px width)</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
        }
        nav {
            background-color: #f0f0f0;
            padding: 10px;
            margin-bottom: 20px;
            width: 400px; /* Reduced from 600px to 400px */
            box-sizing: border-box;
        }
        ul {
            list-style-type: none;
            padding: 0;
            margin: 0;
        }
        li {
            display: inline-block;
            margin-right: 10px;
            margin-bottom: 15px;
        }
        a {
            text-decoration: none;
            color: #333;
            padding: 5px 10px;
            border-radius: 3px;
            background-color: #e0e0e0;
        }
        .controls {
            margin-top: 20px;
            width: 400px; /* Reduced from 600px to 400px to match nav */
        }
        .control-item {
            margin-bottom: 10px;
        }
        #item-count-value {
            margin-left: 10px;
        }
    </style>
</head>
<body>
    <nav id="main-nav">
        <ul>
            <li><a href="#">Home</a></li>
            <li><a href="#">About</a></li>
            <li><a href="#">Services</a></li>
            <li><a href="#">Products</a></li>
            <li><a href="#">Blog</a></li>
            <li><a href="#">Contact</a></li>
            <li><a href="#">FAQ</a></li>
            <li><a href="#">Support</a></li>
            <li><a href="#">Portfolio</a></li>
            <li><a href="#">Team</a></li>
            <li><a href="#">Careers</a></li>
            <li><a href="#">Partners</a></li>
            <li><a href="#">News</a></li>
            <li><a href="#">Events</a></li>
        </ul>
    </nav>

    <div class="controls">
        <div class="control-item">
            <label for="item-count">Number of visible items:</label>
            <input type="range" id="item-count" min="4" max="14" value="14">
            <span id="item-count-value">14</span>
        </div>
        <div class="control-item">
            <label>
                <input type="checkbox" id="balance-toggle"> Enable text-wrap: balance
            </label>
        </div>
    </div>

    <script>
        const nav = document.getElementById('main-nav');
        const toggle = document.getElementById('balance-toggle');
        const itemCountSlider = document.getElementById('item-count');
        const itemCountValue = document.getElementById('item-count-value');
        const navItems = nav.querySelectorAll('li');

        function updateVisibleItems(count) {
            navItems.forEach((item, index) => {
                item.style.display = index < count ? 'inline-block' : 'none';
            });
        }

        function updateTextWrap() {
            if (toggle.checked) {
                nav.style.textWrap = 'balance';
            } else {
                nav.style.textWrap = '';
            }
        }

        toggle.addEventListener('change', updateTextWrap);

        itemCountSlider.addEventListener('input', function() {
            const count = parseInt(this.value);
            itemCountValue.textContent = count;
            updateVisibleItems(count);
        });

        // Initialize with all items visible and default text-wrap
        updateVisibleItems(14);
        updateTextWrap();
    </script>
</body>
</html>

Here are the key changes I've made:

  1. Reduced the width of the nav element from 600px to 400px:

    nav {
        /* ... other properties ... */
        width: 400px; /* Reduced from 600px to 400px */
    }
  2. Adjusted the .controls container to match the new width of the navigation area:

    .controls {
        margin-top: 20px;
        width: 400px; /* Reduced from 600px to 400px to match nav */
    }

These changes will have the following effects on the demo:

  1. The navigation menu now has a more constrained width of 400px, which will make the wrapping behavior of the menu items more pronounced and easier to observe.
  2. The difference between balanced and normal text wrapping will be even more noticeable, especially when toggling the "Enable text-wrap: balance" checkbox.
  3. Users will be able to see how the layout adapts to a narrower space, which is common in responsive web design scenarios.

This update enhances the demonstration of text wrapping behaviors in a highly constrained space. It will be particularly useful for showcasing how text-wrap: balance can improve the readability and aesthetics of tightly packed navigation menus.

The narrower width will likely cause more wrapping, even with fewer items visible, allowing users to more clearly see the effects of both the item count slider and the text-wrap balance toggle.

Is there anything else you'd like me to adjust or explain about this update?

@simonw
Copy link
Author

simonw commented Oct 20, 2024

In testing this I found it worked in Safari but did not work in Firefox - I fixed that by switching from inline-block to just inline on those list items.

Here are the changes I made manually: https://gist.github.com/simonw/776e2a925973f889cf49ba0f5c679d5e/revisions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment