when developing a site with vuetify. there is this layout:
The problem is that I used display absolute in the copy-code icon, so if I scroll to the right the code, I get this:
If I try to set display from absolute to fixed, I do not know why, I find the icon no more in the code snippet but in the top-right corner of the page:
This is the code of the most inner component (the code snippet):
<template>
<div>
<v-fade-transition>
<v-sheet class=”code d-flex grey–text text–lighten-3 pa-4” :color=”background” @mouseenter=”showCopy = true” @mouseleave=”showCopy = false”>
<v-fade-transition>
<v-btn v-if=”showCopy” flat icon class=”copy” color=”success lighten-3” @click=”copyCode”>
<v-icon>content_copy</v-icon>
</v-btn>
</v-fade-transition>
<v-layout column>
<v-flex
v-for=”(row, index) of rows”
:key=”index”
:class=”getClass(index)”
@mouseenter=”rowEntered(index)”
@mouseleave=”rowLeft(index)”
@click=”rowClicked(index)”
\>
<span class=”orange–text text–lighten-3 mr-3 code-row”>{ getRowText(index + 1) }</span>
<span>{ row }</span>
</v-flex>
</v-layout>
</v-sheet>
</v-fade-transition>
<v-snackbar v-model=”showSnackbar” color=”success”>
<span>Testo copiato negli appunti!!!</span>
<v-btn dark flat @click=”showSnackbar = false”>Close</v-btn>
</v-snackbar>
</div>
</template>
<script lang=”ts”>
import vue.js from ‘vue’;
import { Component, Prop } from ‘vue-property-decorator’;
import copyToClipboard from ‘copy-to-clipboard’;
@Component({
components: {}
})
export default class AppExamCardCode extends vue.js {
@Prop({ type: String, required: true })
readonly code!: string;
readonly color = ‘grey’;
readonly darkenDefault = ‘darken-3’;
readonly darkenSelected = ‘darken-2’;
showCopy = false;
showSnackbar = false;
hovered = -1;
selected: number[] = [];
get background(): string {
return this.color + ‘ ‘ + this.darkenDefault;
}
get rows(): string[] {
return this.code.split(‘\n’);
}
//rowClicked, rowLeft, rowEntered, getClass(returns only row background color, getRowText),
copyCode(): void {
copyToClipboard(this.code);
this.showSnackbar = true;
}
}
</script>
<style scoped>
.code {
border-radius: 12px;
overflow-x: auto;
letter-spacing: 0.5px;
word-spacing: 1px;
font-family: “Inconsolata”, monospace;
white-space: pre;
font-weight: 300;
font-size: 15px;
}
.code-row {
letter-spacing: 0.8px;
}
.copy {
position: absolute;
top: 0;
right: 0;
margin: 5px;
}
</style>
This is where it is contained: (AppExamCardCodeExercise)
<template>
<div class=”code-exercise”>
<app-exam-card-code :code=”exercise.code” />
<app-exam-card-code-answer :solution=”exercise.solution” :showAnswers=”showAnswers”/>
</div>
</template>
Contained in AppExamCardExercise:
<template>
<div>
<app-exam-card-true-or-false-exercise v-if=”isTrueOrFalse” :showAnswers=”showAnswers”/>
<app-exam-card-code-exercise v-else :showAnswers=”showAnswers”/>
</div>
</template>
Contained in AppExamCard:
<template>
<div>
<v-scale-transition>
<v-card v-if=”show” class=”exam-card” :class=”cardClass” flat>
<!– omitted –>
</v-toolbar>
<v-card-text>
<v-slide-y-transition mode=”out-in”>
<v-layout row pa-5 :key=”current”>
<v-flex xs12>
<app-exam-card-score v-if=”isFinished && showScore” />
<app-exam-card-exercise v-else :showAnswers=”showAnswers” />
</v-flex>
</v-layout>
</v-slide-y-transition>
</v-card-text>
<v-card-actions>
<!– omitted –>
</v-card-actions>
</v-card>
</v-scale-transition>
</div>
</template>
Solution :
the problem is that the copy icon is position: absolute and the code block (with the scrollbar) is position: relative, so it scrolls together.
Set the code block to position: static and then wrap it in a div and set that div to position: relative, so the copy-button is relative to the parent-parent div (which is not scrollable)
HTML
<div class=”fix”>
<code>
<span class=”copy”>Copy</span>
[…]
</code>
</div>
CSS
.fix {
position: relative;
}
.fix code {
position: static;
}