mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Change overflow calculation to be calculated after compute_absolute_position.
Also include absolutely positioned elements in the overflow rect calculation. Fixes #7797.
This commit is contained in:
parent
4f51710ed3
commit
695b7491fe
10 changed files with 75 additions and 105 deletions
|
@ -42,7 +42,6 @@ use flow::{ImmutableFlowUtils, LateAbsolutePositionInfo, MutableFlowUtils, Opaqu
|
||||||
use flow::{LAYERS_NEEDED_FOR_DESCENDANTS, NEEDS_LAYER};
|
use flow::{LAYERS_NEEDED_FOR_DESCENDANTS, NEEDS_LAYER};
|
||||||
use flow::{PostorderFlowTraversal, PreorderFlowTraversal, mut_base};
|
use flow::{PostorderFlowTraversal, PreorderFlowTraversal, mut_base};
|
||||||
use flow::{self, BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ForceNonfloatedFlag};
|
use flow::{self, BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ForceNonfloatedFlag};
|
||||||
use flow_ref;
|
|
||||||
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, HAS_LAYER};
|
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, HAS_LAYER};
|
||||||
use fragment::{SpecificFragmentInfo};
|
use fragment::{SpecificFragmentInfo};
|
||||||
use gfx::display_list::{ClippingRegion, DisplayList};
|
use gfx::display_list::{ClippingRegion, DisplayList};
|
||||||
|
@ -478,45 +477,6 @@ impl<'a> PreorderFlowTraversal for AbsoluteAssignBSizesTraversal<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The store-overflow traversal particular to absolute flows.
|
|
||||||
///
|
|
||||||
/// Propagate overflow up the Absolute flow tree and update overflow up to and
|
|
||||||
/// not including the root of the Absolute flow tree.
|
|
||||||
/// After that, it is up to the normal store-overflow traversal to propagate
|
|
||||||
/// it further up.
|
|
||||||
pub struct AbsoluteStoreOverflowTraversal<'a>{
|
|
||||||
pub layout_context: &'a LayoutContext<'a>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> PostorderFlowTraversal for AbsoluteStoreOverflowTraversal<'a> {
|
|
||||||
#[inline]
|
|
||||||
fn process(&self, flow: &mut Flow) {
|
|
||||||
{
|
|
||||||
// This will be taken care of by the normal store-overflow traversal.
|
|
||||||
let flow: &Flow = flow;
|
|
||||||
if flow.contains_roots_of_absolute_flow_tree() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
flow.mutate_fragments(&mut |f: &mut Fragment| {
|
|
||||||
match f.specific {
|
|
||||||
SpecificFragmentInfo::InlineBlock(ref mut info) => {
|
|
||||||
let block = flow_ref::deref_mut(&mut info.flow_ref);
|
|
||||||
(block.as_mut_block() as &mut Flow).early_store_overflow(self.layout_context);
|
|
||||||
}
|
|
||||||
SpecificFragmentInfo::InlineAbsolute(ref mut info) => {
|
|
||||||
let block = flow_ref::deref_mut(&mut info.flow_ref);
|
|
||||||
(block.as_mut_block() as &mut Flow).early_store_overflow(self.layout_context);
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
flow.early_store_overflow(self.layout_context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum BlockType {
|
pub enum BlockType {
|
||||||
Replaced,
|
Replaced,
|
||||||
NonReplaced,
|
NonReplaced,
|
||||||
|
@ -1016,7 +976,6 @@ impl BlockFlow {
|
||||||
relative_containing_block_size: self.fragment.content_box().size,
|
relative_containing_block_size: self.fragment.content_box().size,
|
||||||
relative_containing_block_mode: self.fragment.style().writing_mode,
|
relative_containing_block_mode: self.fragment.style().writing_mode,
|
||||||
};
|
};
|
||||||
kid.late_store_overflow(layout_context)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
|
if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
|
||||||
|
@ -1073,11 +1032,6 @@ impl BlockFlow {
|
||||||
// the block-size of its containing block, which may also be an absolute flow.
|
// the block-size of its containing block, which may also be an absolute flow.
|
||||||
(&mut *self as &mut Flow).traverse_preorder_absolute_flows(
|
(&mut *self as &mut Flow).traverse_preorder_absolute_flows(
|
||||||
&mut AbsoluteAssignBSizesTraversal(layout_context));
|
&mut AbsoluteAssignBSizesTraversal(layout_context));
|
||||||
// Store overflow for all absolute descendants.
|
|
||||||
(&mut *self as &mut Flow).traverse_postorder_absolute_flows(
|
|
||||||
&mut AbsoluteStoreOverflowTraversal {
|
|
||||||
layout_context: layout_context,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't remove the dirty bits yet if we're absolutely-positioned, since our final size
|
// Don't remove the dirty bits yet if we're absolutely-positioned, since our final size
|
||||||
|
@ -1795,7 +1749,6 @@ impl Flow for BlockFlow {
|
||||||
self.base.thread_id = parent_thread_id;
|
self.base.thread_id = parent_thread_id;
|
||||||
if self.base.restyle_damage.intersects(REFLOW_OUT_OF_FLOW | REFLOW) {
|
if self.base.restyle_damage.intersects(REFLOW_OUT_OF_FLOW | REFLOW) {
|
||||||
self.assign_block_size(layout_context);
|
self.assign_block_size(layout_context);
|
||||||
(self as &mut Flow).early_store_overflow(layout_context);
|
|
||||||
// Don't remove the restyle damage; `assign_block_size` decides whether that is
|
// Don't remove the restyle damage; `assign_block_size` decides whether that is
|
||||||
// appropriate (which in the case of e.g. absolutely-positioned flows, it is not).
|
// appropriate (which in the case of e.g. absolutely-positioned flows, it is not).
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,11 +220,6 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
|
||||||
if impacted {
|
if impacted {
|
||||||
mut_base(self).thread_id = parent_thread_id;
|
mut_base(self).thread_id = parent_thread_id;
|
||||||
self.assign_block_size(layout_context);
|
self.assign_block_size(layout_context);
|
||||||
// FIXME(pcwalton): Should use `early_store_overflow()` here but that fails due to a
|
|
||||||
// compiler bug (`Self` does not have a constant size).
|
|
||||||
if !self.contains_relatively_positioned_fragments() {
|
|
||||||
self.store_overflow(layout_context)
|
|
||||||
}
|
|
||||||
mut_base(self).restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW);
|
mut_base(self).restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW);
|
||||||
}
|
}
|
||||||
impacted
|
impacted
|
||||||
|
@ -252,9 +247,6 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
|
||||||
// FIXME(#2795): Get the real container size.
|
// FIXME(#2795): Get the real container size.
|
||||||
let container_size = Size2D::zero();
|
let container_size = Size2D::zero();
|
||||||
for kid in mut_base(self).children.iter_mut() {
|
for kid in mut_base(self).children.iter_mut() {
|
||||||
if base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
let kid_overflow = base(kid).overflow;
|
let kid_overflow = base(kid).overflow;
|
||||||
let kid_position = base(kid).position.to_physical(base(kid).writing_mode,
|
let kid_position = base(kid).position.to_physical(base(kid).writing_mode,
|
||||||
container_size);
|
container_size);
|
||||||
|
@ -461,11 +453,6 @@ pub trait ImmutableFlowUtils {
|
||||||
/// Returns true if this flow is an inline flow.
|
/// Returns true if this flow is an inline flow.
|
||||||
fn is_inline_flow(self) -> bool;
|
fn is_inline_flow(self) -> bool;
|
||||||
|
|
||||||
/// Returns true if this flow can have its overflow area calculated early (during its
|
|
||||||
/// block-size assignment) or false if it must have its overflow area calculated late (during
|
|
||||||
/// its parent's block-size assignment).
|
|
||||||
fn can_calculate_overflow_area_early(self) -> bool;
|
|
||||||
|
|
||||||
/// Dumps the flow tree for debugging.
|
/// Dumps the flow tree for debugging.
|
||||||
fn dump(self);
|
fn dump(self);
|
||||||
|
|
||||||
|
@ -502,12 +489,6 @@ pub trait MutableFlowUtils {
|
||||||
/// Calls `repair_style` and `bubble_inline_sizes`. You should use this method instead of
|
/// Calls `repair_style` and `bubble_inline_sizes`. You should use this method instead of
|
||||||
/// calling them individually, since there is no reason not to perform both operations.
|
/// calling them individually, since there is no reason not to perform both operations.
|
||||||
fn repair_style_and_bubble_inline_sizes(self, style: &Arc<ComputedValues>);
|
fn repair_style_and_bubble_inline_sizes(self, style: &Arc<ComputedValues>);
|
||||||
|
|
||||||
/// Calls `store_overflow()` if the overflow can be calculated early.
|
|
||||||
fn early_store_overflow(self, layout_context: &LayoutContext);
|
|
||||||
|
|
||||||
/// Calls `store_overflow()` if the overflow cannot be calculated early.
|
|
||||||
fn late_store_overflow(self, layout_context: &LayoutContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MutableOwnedFlowUtils {
|
pub trait MutableOwnedFlowUtils {
|
||||||
|
@ -1310,13 +1291,6 @@ impl<'a> ImmutableFlowUtils for &'a Flow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this flow can have its overflow area calculated early (during its
|
|
||||||
/// block-size assignment) or false if it must have its overflow area calculated late (during
|
|
||||||
/// its parent's block-size assignment).
|
|
||||||
fn can_calculate_overflow_area_early(self) -> bool {
|
|
||||||
!self.contains_relatively_positioned_fragments()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Dumps the flow tree for debugging.
|
/// Dumps the flow tree for debugging.
|
||||||
fn dump(self) {
|
fn dump(self) {
|
||||||
self.dump_with_level(0)
|
self.dump_with_level(0)
|
||||||
|
@ -1395,20 +1369,6 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
|
||||||
|
|
||||||
traversal.process(*self)
|
traversal.process(*self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calls `store_overflow()` if the overflow can be calculated early.
|
|
||||||
fn early_store_overflow(self, layout_context: &LayoutContext) {
|
|
||||||
if self.can_calculate_overflow_area_early() {
|
|
||||||
self.store_overflow(layout_context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Calls `store_overflow()` if the overflow cannot be calculated early.
|
|
||||||
fn late_store_overflow(self, layout_context: &LayoutContext) {
|
|
||||||
if !self.can_calculate_overflow_area_early() {
|
|
||||||
self.store_overflow(layout_context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MutableOwnedFlowUtils for FlowRef {
|
impl MutableOwnedFlowUtils for FlowRef {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use block::{AbsoluteAssignBSizesTraversal, AbsoluteStoreOverflowTraversal};
|
use block::AbsoluteAssignBSizesTraversal;
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use display_list_builder::{FragmentDisplayListBuilding, InlineFlowDisplayListBuilding};
|
use display_list_builder::{FragmentDisplayListBuilding, InlineFlowDisplayListBuilding};
|
||||||
use euclid::{Point2D, Rect, Size2D};
|
use euclid::{Point2D, Rect, Size2D};
|
||||||
|
@ -1598,11 +1598,6 @@ impl Flow for InlineFlow {
|
||||||
// the block-size of its containing block, which may also be an absolute flow.
|
// the block-size of its containing block, which may also be an absolute flow.
|
||||||
(&mut *self as &mut Flow).traverse_preorder_absolute_flows(
|
(&mut *self as &mut Flow).traverse_preorder_absolute_flows(
|
||||||
&mut AbsoluteAssignBSizesTraversal(layout_context));
|
&mut AbsoluteAssignBSizesTraversal(layout_context));
|
||||||
// Store overflow for all absolute descendants.
|
|
||||||
(&mut *self as &mut Flow).traverse_postorder_absolute_flows(
|
|
||||||
&mut AbsoluteStoreOverflowTraversal {
|
|
||||||
layout_context: layout_context,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.base.position.size.block = match self.lines.last() {
|
self.base.position.size.block = match self.lines.last() {
|
||||||
|
@ -1627,7 +1622,6 @@ impl Flow for InlineFlow {
|
||||||
relative_containing_block_size: containing_block_size,
|
relative_containing_block_size: containing_block_size,
|
||||||
relative_containing_block_mode: writing_mode,
|
relative_containing_block_mode: writing_mode,
|
||||||
};
|
};
|
||||||
(block.as_mut_block() as &mut Flow).late_store_overflow(layout_context);
|
|
||||||
}
|
}
|
||||||
SpecificFragmentInfo::InlineAbsolute(ref mut info) => {
|
SpecificFragmentInfo::InlineAbsolute(ref mut info) => {
|
||||||
let block = flow_ref::deref_mut(&mut info.flow_ref);
|
let block = flow_ref::deref_mut(&mut info.flow_ref);
|
||||||
|
@ -1635,7 +1629,6 @@ impl Flow for InlineFlow {
|
||||||
relative_containing_block_size: containing_block_size,
|
relative_containing_block_size: containing_block_size,
|
||||||
relative_containing_block_mode: writing_mode,
|
relative_containing_block_mode: writing_mode,
|
||||||
};
|
};
|
||||||
(block.as_mut_block() as &mut Flow).late_store_overflow(layout_context);
|
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
|
@ -484,9 +484,6 @@ pub fn traverse_flow_tree_preorder(
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}, shared_layout_context);
|
}, shared_layout_context);
|
||||||
|
|
||||||
let layout_context = LayoutContext::new(shared_layout_context);
|
|
||||||
flow_ref::deref_mut(root).late_store_overflow(&layout_context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_display_list_for_subtree(
|
pub fn build_display_list_for_subtree(
|
||||||
|
|
|
@ -98,8 +98,6 @@ pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
|
||||||
let assign_block_sizes = AssignBSizesAndStoreOverflow { layout_context: &layout_context };
|
let assign_block_sizes = AssignBSizesAndStoreOverflow { layout_context: &layout_context };
|
||||||
|
|
||||||
doit(root, assign_inline_sizes, assign_block_sizes);
|
doit(root, assign_inline_sizes, assign_block_sizes);
|
||||||
|
|
||||||
root.late_store_overflow(&layout_context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_display_list_for_subtree(root: &mut FlowRef,
|
pub fn build_display_list_for_subtree(root: &mut FlowRef,
|
||||||
|
|
|
@ -12,7 +12,7 @@ use block::{self, BlockFlow, CandidateBSizeIterator, ISizeAndMarginsComputer};
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
|
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
|
||||||
use euclid::{Point2D, Rect};
|
use euclid::{Point2D, Rect};
|
||||||
use flow::{IMPACTED_BY_RIGHT_FLOATS, ImmutableFlowUtils, MutableFlowUtils, OpaqueFlow};
|
use flow::{IMPACTED_BY_RIGHT_FLOATS, ImmutableFlowUtils, OpaqueFlow};
|
||||||
use flow::{self, EarlyAbsolutePositionInfo, Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS};
|
use flow::{self, EarlyAbsolutePositionInfo, Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS};
|
||||||
use fragment::{Fragment, FragmentBorderBoxIterator};
|
use fragment::{Fragment, FragmentBorderBoxIterator};
|
||||||
use gfx::display_list::DisplayList;
|
use gfx::display_list::DisplayList;
|
||||||
|
@ -762,7 +762,7 @@ pub trait TableLikeFlow {
|
||||||
|
|
||||||
impl TableLikeFlow for BlockFlow {
|
impl TableLikeFlow for BlockFlow {
|
||||||
fn assign_block_size_for_table_like_flow<'a>(&mut self,
|
fn assign_block_size_for_table_like_flow<'a>(&mut self,
|
||||||
layout_context: &'a LayoutContext<'a>,
|
_: &'a LayoutContext<'a>,
|
||||||
block_direction_spacing: Au) {
|
block_direction_spacing: Au) {
|
||||||
debug_assert!(self.fragment.style.get_inheritedtable().border_collapse ==
|
debug_assert!(self.fragment.style.get_inheritedtable().border_collapse ==
|
||||||
border_collapse::T::separate || block_direction_spacing == Au(0));
|
border_collapse::T::separate || block_direction_spacing == Au(0));
|
||||||
|
@ -842,7 +842,6 @@ impl TableLikeFlow for BlockFlow {
|
||||||
relative_containing_block_size: self.fragment.content_box().size,
|
relative_containing_block_size: self.fragment.content_box().size,
|
||||||
relative_containing_block_mode: self.fragment.style().writing_mode,
|
relative_containing_block_mode: self.fragment.style().writing_mode,
|
||||||
};
|
};
|
||||||
kid.late_store_overflow(layout_context)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
use construct::FlowConstructor;
|
use construct::FlowConstructor;
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use css::matching::{ApplicableDeclarations, ElementMatchMethods, MatchMethods, StyleSharingResult};
|
use css::matching::{ApplicableDeclarations, ElementMatchMethods, MatchMethods, StyleSharingResult};
|
||||||
use flow::{MutableFlowUtils, PostorderFlowTraversal, PreorderFlowTraversal};
|
use flow::{PostorderFlowTraversal, PreorderFlowTraversal};
|
||||||
use flow::{self, Flow};
|
use flow::{self, Flow};
|
||||||
use gfx::display_list::OpaqueNode;
|
use gfx::display_list::OpaqueNode;
|
||||||
use incremental::{self, BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
|
use incremental::{self, BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
|
||||||
|
@ -360,7 +360,6 @@ impl<'a> PostorderFlowTraversal for AssignBSizesAndStoreOverflow<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
flow.assign_block_size(self.layout_context);
|
flow.assign_block_size(self.layout_context);
|
||||||
flow.early_store_overflow(self.layout_context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -378,6 +377,7 @@ impl<'a> PreorderFlowTraversal for ComputeAbsolutePositions<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn process(&self, flow: &mut Flow) {
|
fn process(&self, flow: &mut Flow) {
|
||||||
flow.compute_absolute_position(self.layout_context);
|
flow.compute_absolute_position(self.layout_context);
|
||||||
|
flow.store_overflow(self.layout_context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,18 @@
|
||||||
"deleted": [],
|
"deleted": [],
|
||||||
"items": {
|
"items": {
|
||||||
"reftest": {
|
"reftest": {
|
||||||
|
"css/abs-overflow-stackingcontext.html": [
|
||||||
|
{
|
||||||
|
"path": "css/abs-overflow-stackingcontext.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/_mozilla/css/abs-overflow-stackingcontext_ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/_mozilla/css/abs-overflow-stackingcontext.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
"css/abs_float_pref_width.html": [
|
"css/abs_float_pref_width.html": [
|
||||||
{
|
{
|
||||||
"path": "css/abs_float_pref_width.html",
|
"path": "css/abs_float_pref_width.html",
|
||||||
|
@ -4750,6 +4762,18 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"reftest_nodes": {
|
"reftest_nodes": {
|
||||||
|
"css/abs-overflow-stackingcontext.html": [
|
||||||
|
{
|
||||||
|
"path": "css/abs-overflow-stackingcontext.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/_mozilla/css/abs-overflow-stackingcontext_ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/_mozilla/css/abs-overflow-stackingcontext.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
"css/abs_float_pref_width.html": [
|
"css/abs_float_pref_width.html": [
|
||||||
{
|
{
|
||||||
"path": "css/abs_float_pref_width.html",
|
"path": "css/abs_float_pref_width.html",
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel='match' href='abs-overflow-stackingcontext_ref.html'>
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
perspective: 1000px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
position: absolute;
|
||||||
|
top: 25vh;
|
||||||
|
left: 25vw;
|
||||||
|
width: 50vw;
|
||||||
|
height: 50vh;
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
position: absolute;
|
||||||
|
top: 25vh;
|
||||||
|
left: 25vw;
|
||||||
|
width: 50vw;
|
||||||
|
height: 50vh;
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue