Tips for arranging menu items along a curved counter

One of my clients has requested a unique design feature—a curved menu. The menu items are currently represented by red squares, but they should be positioned to follow the curve of the pink squares on the blue bar. How can I achieve this effect?

Should I incorporate the menu items directly into an SVG, or should I blend the SVG with a background image and then use flexbox to position the menu items accordingly?

Additionally, the design should be responsive to screens with a width of approximately 1000px. Once we reach that threshold, I plan to transition the menu to a mobile-friendly version that is already in use on other pages.

Answer №1

<html>
  <body height="100%" width="100%">
    <svg height="100%" width="100%" viewbox="0 0 100 100" preserveAspectRatio="none">
         <path d="M 10 10 Q 50 50 90 50 v -40 h -80" fill="cyan" transform="scale(1.05,1.05) translate(-4.5,-.5)"/>
      <path id="path" d="M 10 10 Q 50 50 90 50" fill="none" stroke="yellow"/>
      <text font-size="4">
        <textPath href="#path" textPath="stretch">
          <tspan dx="5">Unique1</tspan>
          <tspan dx="10">Unique2</tspan>
          <tspan dx="10">Unique3</tspan>
        </textPath>
        
        
      </text>
     
      
   
      
    </svg>
  </body>
</html>

Answer №2

An effective method to achieve this is by calculating the position of each rectangle from the top and left edges of the image and also determining the width and height of the image itself.

The units used for measurements do not matter as long as they are consistent across all rectangles.

By obtaining a series of top and left offsets, CSS can be utilized to calculate the percentage positioning of each rectangle relative to the top and left edges of the image.

For each li:nth-child(n) set, include the two CSS variables: --left: x; --top: y; representing the measured values, and in the ul include --w: ; --h:

Subsequently, position the nth-child element as a percentage relative to the top left corner of the image using CSS calc.

Answer №3

Every idea is welcome, even the bad ones.

Here's a quirky suggestion – what if we embrace the chaos and avoid calculating or hardcoding X,Y positions altogether?

Imagine using keyPoints to effortlessly position the <text> element along a path.

And hey, for those who prefer a static look, simply set dur="0s" to skip the animation.

<style>
  svg{
    width:90vw;
    background:pink;
  }
</style>
<svg viewBox="0 0 200 50">
  <path id="slope" fill="none" stroke="red" d="m10,10c40,0,45,35,180,35"></path>
  <text>One
    <animateMotion dur="1s" fill="freeze" keyPoints="0;.1" keyTimes="0;1" calcMode="linear">
      <mpath href="#slope"></mpath>
    </animateMotion>
  </text>
  <text>Two
    <animateMotion dur="1s" fill="freeze" keyPoints="0;.4" keyTimes="0;1" calcMode="linear">
      <mpath href="#slope"></mpath>
    </animateMotion>
  </text>
  <text>Three
    <animateMotion dur="1s" fill="freeze" keyPoints="0;.75" keyTimes="0;1" calcMode="linear">
      <mpath href="#slope"></mpath>
    </animateMotion>
  </text>
</svg>

Answer №4

After reviewing the screenshot you provided, there are a couple of approaches you could take to address this issue. The complexity of the solution depends on how you are incorporating the background graphic. If the background image resizes, the offset required for each navigation item will vary slightly.

Here are two straightforward solutions:

ul {
  display: flex;
}

li {
  list-style: none;
  margin: 0 3rem;
  position: relative;
  width:100%;
}
li:nth-child(2) {
  top: 20px;
}
li:nth-child(3) {
  top: 40px;
}
li:nth-child(4) {
  top: 50px;
}
li:nth-child(5), li:nth-child(6), li:nth-child(7), li:nth-child(8) {
  top: 60px;
}
<nav>
  <ul>
    <li><a href='#' title=''>Link</a></li>
    <li><a href='#' title=''>Link</a></li>
    <li><a href='#' title=''>Link</a></li>
    <li><a href='#' title=''>Link</a></li>
    <li><a href='#' title=''>Link</a></li>
    <li><a href='#' title=''>Link</a></li>
    <li><a href='#' title=''>Link</a></li>
    <li><a href='#' title=''>Link</a></li>
  </ul>
</nav>

The first solution is a simple approach where you can adjust the positioning of items using nth-child. This method would be cleaner if you are using SCSS, as you could use an iterator for this purpose. However, to make it fully responsive, you may need to incorporate media queries at different breakpoints to align the background curve with the links.

For the JavaScript approach:

let endingCurve = 80;
let currentCurve = 0;
let navItems = document.querySelectorAll('li');
let offsetPerItem = (endingCurve / navItems.length);
navItems.forEach(item => {
  currentCurve = currentCurve + offsetPerItem
  item.style.top = `${currentCurve}px`;
});
ul {
  display: flex;
}

li {
  list-style: none;
  margin: 0 3rem;
  position: relative;
}
<nav>
  <ul>
    <li><a href='' title=''>Link</a></li>
    <li><a href='' title=''>Link</a></li>
    <li><a href='' title=''>Link</a></li>
    <li><a href='' title=''>Link</a></li>
    <li><a href='' title=''>Link</a></li>
    <li><a href='' title=''>Link</a></li>
    <li><a href='' title=''>Link</a></li>
    <li><a href='' title=''>Link</a></li>
  </ul>
</nav>

In this JavaScript solution, you set an ending curve, determine the number of items in your navigation, and calculate the offset per item based on the curve. Then, you iterate through each item and apply a top style to adjust the position. This method is similar to using nth-child in CSS but with the flexibility to modify the ending curve value for different effects.

There are more advanced JavaScript solutions that could be developed with additional information, such as whether the background image curve is fixed, scales with the browser, or is in a specific format like SVG. Nonetheless, these approaches should provide a good starting point for your implementation!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Searching for a specific element using a CSS selector

Looking for a way to find an element using a CSS selector in Chrome, I followed these steps: Right-click on the object Select "inspect" Right-click on the highlighted area in Chrome developer tools Choose "copy" Click on "copy selector" This is the cod ...

What is the best way to remove table row data fetched from an API within a table?

Can someone assist me with deleting the table tr from the user table, where data is retrieved from an API? I have attempted the code below: $("principleTable").find("tr").hide(); $("#delAgentModal").modal("hide"); ...

Error message displayed: "An error occurred while processing the VueJS InertiaJS Uncaught (in promise) TypeError. It seems that the property 'search'

Currently, I am working on a Vue JS project with Inertia. One of the features I am implementing is a list that allows users to filter by name. data() { return { selectedUser: this.value, selected: null, search: & ...

Experiencing the Pause: A Fresh Take on

I'm currently using this slideshow for a project, and I need to understand if it's possible to resume its interval. The current issue is that when you hover over the slideshow, the progress bar stops. But once you remove the mouse, it continues f ...

Set the CSS/HTML to make two child elements occupy 50% of the height of the parent container div

This task seems deceptively simple, yet I am struggling to find a straightforward solution. Language: (HTML) <div class="col-6-12 subcontent-outer"> <div class="subcontent"> <h1>Header</h1> ...

Ways to dynamically update the content of an HTML table without the need to reload the page

I'm currently working on an HTML table that retrieves data from a database and includes a button for deleting selected records. Here is what the table layout looks like: name phone links john 6562 link1 link2 link3 ___________ ...

Designing my website to resize and adapt to different screen resolutions using CSS

As I navigate my first week of CSS, HTML, and PHP programming, I encountered a problem with text overlapping and causing issues on my site when scaled according to window size. I'm seeking clarity on what mistakes I may be making. Despite trying medi ...

Tips for organizing components in jQuery Mobile

Displaying a survey creation form: <!-- HTML structure --> <div data-role="page" data-theme="b"> <div data-role="header"> <h1> Create Survey </h1> </div> <div id="main" data ...

Using asynchronous data in Angular 2 animations

Currently, I have developed a component that fetches a dataset of skills from my database. Each skill in the dataset contains a title and a percentage value. My objective is to set the initial width value of each div to 0% and then dynamically adjust it t ...

What could be causing my Laravel Vue app web page to be blank?

I am facing an issue after installing Vue in Laravel and running the command npm run watch with php artisan serve. When I load the page, nothing appears without any error messages. What could be causing this problem? main.js import { createApp } from &apo ...

Having difficulty resolving issues with the chat box (div) scroll bar staying fixed at the bottom

I am currently working on a chat application and I am facing an issue with fixing the scroll bar at the bottom of a div when loading my PHP file. I have already written a script to achieve this, but despite accessing it using CSS Id, I am having trouble ge ...

Converting XPath into CSS

I really need your assistance in converting XPath to CSS. I have this code snippet and XPath expression: /descendant::p/parent::*/child::p[position()=1] ... The selected elements will be (B D F H) <?xml version="1.0" ?> <book> <title&g ...

Arrangement of div elements tailored to fit the size of the viewport

I am working on creating a grid of divs that will cover the entire viewport. To start, I want to have a grid that is 7 divs wide and 10 divs high. Below is the code snippet I've written so far to set the size of the div elements: function adjustHeig ...

Update the content on the webpage to display the SQL data generated by selecting options from various dropdown

My database table is structured like this: Name │ Favorite Color │ Age │ Pet ────────┼────────────────┼───────┼─────── Rupert │ Green │ 21 │ ...

I developed a compact application utilizing Node.js in tandem with Express framework

There is an issue with the GPA calculator app built using Node.js and Express. It works fine for a single user, but when multiple users try to use it simultaneously, the scores are being combined, resulting in incorrect values. I need to create an app that ...

Stop Mat-chip from automatically inserting a row upon selection

I am working on preventing the automatic addition of a row by the mat-chip module after a single chip has been selected. Even though the max chip count is set to 1, the input remains enabled and adds a new row beneath it as if the user can still type more ...

Is it possible to securely share login details on the internet?

I'm currently brainstorming different ways to securely display FTP, database, and hosting information for website projects on my project management site. One potential solution I'm considering is encrypting the passwords and developing an applica ...

Equal dimensions for all cards in the TailwindCSS gallery display

I am currently working on an image gallery in React with Tailwind CSS. Here's a glimpse of how it looks: https://i.stack.imgur.com/ABdFo.png Each image component is structured like this: <div className="flex items-center"> < ...

What are the steps to developing fully offline HTML5 applications?

At times, I find myself in need of writing a small program to visualize some data in a chart or similar format. I've been thinking about using HTML5 through the browser to accomplish this, specifically utilizing its canvas to design a user-friendly in ...

extract the chosen value from the inputted string

When a user selects an option from the dropdown menu, two separate string values are retrieved. For example: <label>Book ID</label><span class="required">*</span> <select class="js-example-basic-single form-control" name="sel_Bo ...