Vue.js Card displayDisplaying cards in a Vue

I've recently started diving into vue.js and I'm honing my skills with vuetify. I've been grappling with this layout for quite some time now but I seem to be stuck. Could someone please guide me through approaching this problem?

I have an array of objects that contains descriptions and images which I aim to display in a specific format as shown in the image below.https://i.sstatic.net/ecrn7.png

The logic behind the layout is as follows - the first card should display a description, the second one, an image. When transitioning to a new row, like the second row, the image should persist just like in the fourth card. The pattern continues with alternating text and image cards starting from the eighth and ninth positions.

<template>
  <div class="home">
    <v-container grid-list-lg>
      <h1>Home</h1>
      <v-layout row>
        <v-flex lg3 v-for="(item, index) in arr" :key="item.id" class="space-bottom">
          <v-card class="mx-auto" max-width="344" outlined>
            <v-list-item three-line>
              <v-list-item-content v-if="index % 2 === 0" height="400px">
                <v-list-item-subtitle>{{item.description}}</v-list-item-subtitle>

                <v-list-item-subtitle class="subtitle-style">
                  <span>
                    <a href="#">Read more</a>
                  </span>
                </v-list-item-subtitle>
              </v-list-item-content>
            </v-list-item>

            <v-hover>
              <template v-slot:default="{ hover }">
                <v-list-item-content v-if="index % 2 !== 0">
                  <img :src="item.imageUrl" />

                  <v-fade-transition>
                    <v-overlay v-if="hover" absolute color="#036358">
                      <v-btn>See more info</v-btn>
                    </v-overlay>
                  </v-fade-transition>
                </v-list-item-content>
              </template>
            </v-hover>
          </v-card>
        </v-flex>
      </v-layout>
    </v-container>
  </div>
</template>

<script>
export default {
  props: {},
  data() {
    return {
      arr: [ {description: "description 1", imageUrl: "https://via.placeholder.com/100"},
             {description: "description 2", imageUrl: "https://via.placeholder.com/100"},
             {description: "description 3", imageUrl: "https://via.placeholder.com/100"},
             {description: "description 4", imageUrl: "https://via.placeholder.com/100"},
             {description: "description 1", imageUrl: "https://via.placeholder.com/100"},
             {description: "description 1", imageUrl: "https://via.placeholder.com/100"}, 
             {description: "description 1", imageUrl: "https://via.placeholder.com/100"},
             {description: "description 2", imageUrl: "https://via.placeholder.com/100"},
             {description: "description 3", imageUrl: "https://via.placeholder.com/100"},
             {description: "description 4", imageUrl: "https://via.placeholder.com/100"},
             {description: "description 1", imageUrl: "https://via.placeholder.com/100"},
             {description: "description 1", imageUrl: "https://via.placeholder.com/100"}]
    };
  }
};
</script>

<style>
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

Currently, the layout looks like this: https://i.sstatic.net/UCOjx.png

Answer №1

Just follow this code snippet:

methods: {
  getCardType(index) {
    return (this.rowLength * 2 + index) % (this.rowLength * 2) >= this.rowLength
      ? index % 2 ? 'text' : 'img'
      : index % 2 ? 'img' : 'text'
  }
}

Set rowLength to 4:

Vue.config.productionTip = false;
Vue.config.devtools = false;

new Vue({
  el: '#app',
  data() {
    return {
      rowLength: 4
    }
  },
  methods: {
    getCardType(index) {
      return (this.rowLength * 2 + index) % (this.rowLength * 2) >= this.rowLength
        ? index % 2 ? 'text' : 'img'
        : index % 2 ? 'img' : 'text'
    }
  }
})
#app {
  display: flex;
  flex-wrap: wrap;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<div id="app">
  <div v-for="n in 100" class="card" :style="{flex: `1 0 ${100/rowLength}%`}">{{getCardType(n - 1)}}</div>
</div>

This can possibly be simplified or adjusted for a different number of items per row.

Here's an updated version that maintains the "chekers" pattern on both odd and even column counts:

getCardType(index) {
  return this.rowLength % 2 ||
  (this.rowLength * 2 + index) % (this.rowLength * 2) >= this.rowLength
  ? index % 2 ? 'text' : 'img'
  : index % 2 ? 'img' : 'text'
}

Vue.config.productionTip = false;
Vue.config.devtools = false;

new Vue({
  el: '#app',
  data() {
    return {
      rowLength: 4
    }
  },
  methods: {
    getCardType(index) {
      return this.rowLength % 2 ||
      (this.rowLength * 2 + index) % (this.rowLength * 2) >= this.rowLength
      ? index % 2 ? 'text' : 'img'
      : index % 2 ? 'img' : 'text'
    }
  }
})
.columns {
  display: flex;
  flex-wrap: wrap;
}
.card {
  padding: 1rem;
  box-sizing: border-box;
}
.img {
  background-color: #f5f5f5;
}
body {
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<div id="app">
  <div>Columns: <input type="number" v-model="rowLength"></div>
  <div class="columns">
    <div v-for="n in 100" class="card"
         :style="{flex: `1 0 ${100/rowLength}%`}"
         :class="[getCardType(n - 1)]"
         >{{getCardType(n - 1)}}
    </div>
  </div>
</div>

To clarify, this function will return either img or text based on the parity of the index, but it reverses the condition on even rows when the number of items per row is even.

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

Automatically update div content using AJAX in a different approach

In my situation, I am facing a unique challenge compared to other queries. I have a div element with the following code <div id="ondiv"><?php ?></div> Within this PHP section are details of people who are currently online. Ideally, when ...

Checkbox click event not triggering properly

I am facing challenges in triggering an onclick event for the "Elevation" checkboxes located at the URL provided above. <input type="checkbox" value="A" id="elevation_A" onclick="changeElevation(this.value);" /> For some reason, the "changeElevati ...

Utilizing Dexie-Query for Real-Time Data Updates in Vue

I am currently utilizing Dexie within my Vue 3 frontend and aiming to seamlessly integrate it. Within the mount() method, I execute a database query similar to the example below, storing the result in a local variable within the Vue template for rendering ...

"Troubleshooting: IE compatibility issue with jQuery's .each and .children functions

I have created an Instagram image slider feed that works well in Chrome, Safari, Firefox, and Opera. However, it fails to function in all versions of Internet Explorer without showing any error messages. To accurately determine the height of images for th ...

Creating form elements in ReactJS dynamically and storing their values in an array

I need to render 3 materialUI TextFields multiple times, depending on the integer input by the user before rendering the form fields (the integer is stored in a variable called groupMembersCount). I am using a functional component in ReactJS with an array ...

Transfer a characteristic from one element to another

I need help with multiple columns of checkboxes and labels. <ul class="column1"> <li> <input value="jan" type="checkbox" /> <label>Jan</label> </li> <li> <input value="feb" t ...

Transition CSS applied only to links containing images

I am trying to figure out how to apply a transition effect only on links that have images, rather than text. Specifically, I want the transition effect to be applied only to the second link in the following example: <a href="#">no image</a> &l ...

AngularJS enables the loading of directives dynamically, but sometimes encounters errors such as "Restricted URI access denied."

Presently, I am in the process of developing a small educational project using HTML5, CSS, JS and AngularJS. Hiccup: Loading an AngularJS Directive in my index.html file Error code [1] - Local browser Error: Access to restricted URI denied Various resp ...

Navigating the Google Maps API: Implementing Scroll Zoom to Focus on a Single Marker

I'm looking for a solution for my project where the scroll zoom function will focus on zooming in on a marker or specific point rather than defaulting to the cursor. The current behavior is that the scroll zoom always centers on the cursor. Can anyone ...

Having trouble getting HTML to render properly in React JS on localhost using Apache server

For the past week, I've been working on resolving an issue. I started by creating a React Application using: npm create react-app After that, I attempted to build it with: npm run build Everything seemed to go smoothly. I generated a build folder ...

Prevent TypeScript from generalizing string literals as types

I have a constant Object called STUDY_TAGS with specific properties const STUDY_TAGS ={ InstanceAvailability: { tag: "00080056", type: "optional", vr: "string" }, ModalitiesinStudy: { tag: "00080061", type: " ...

"Combining the power of JavaScript countdown with PHP date functionality

I have a JavaScript code that generates countdowns based on the user's PC date. I'm looking for a way to modify the script to use a specific timezone like: <?php date_default_timezone_set('Ireland/Dublin'); $date = date('m/d/Y ...

Interacting with distant servers within XD plugins

Currently in the process of developing an XD plugin, with a goal of fetching images from a remote server. Is this achievable and are there specific APIs that can facilitate this task? ...

Determining the file path in HTML5

Can anyone help me with retrieving the file path using html5 javascript once a user selects a file? I require the file path for a specific scenario: In this case, the user uploads a file and pauses it (currently only supported by Mozilla browsers), then c ...

Extracting data from a database using PEAR for Excel: Enumerating columns

One aspect of my website allows users to extract an Excel file using data from a database, with the help of the PEAR library. The Excel table that is generated currently has 32 columns. My main goal is to insert a 33rd column that assigns a number startin ...

What could be the reason for a code running successfully in node but not in the REPL environment?

This is the current script I'm working with: const lib = require('./lib.js'); const fs = require('fs'); const graph = fs.readFileSync('../js-working-dir/add_graph.pb', 'utf8'); const sess = new lib.Session(gr ...

Creating custom directives in Vue2 is just like adding a functionality similar to v

I am in the process of developing a unique directive similar to v-if that will only render if the data passed into the element is not empty. For instance: <div v-if="!_.isEmpty(data.employer)">{{ data.employer.name }}</div> This code snippet ...

Hide the drawer when a user clicks on a currently selected tab

Just starting to explore Material-UI and React here, so please bear with me if I'm making any rookie mistakes. :) I've set up a Drawer component containing a Tabs element with multiple Tab components inside. It's nothing too fancy yet - mos ...

Invoking a URL asynchronously on a website

Unique Font License Dilemma Recently, I came across a unique situation with a font license that required me to query a counter on the font provider's domain every time the typeface was displayed. However, the recommended method of using import in the ...

Handling Google-Strategy authentication in a Vue application with passportjs

I am seeking advice on how to implement the Google strategy of passportjs in my Vue App with Node running in the backend. The Vue app is hosted on localhost:8080, and Node is on localhost:5000 I have successfully set up a Local strategy using: Sending A ...