A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://www.material-react-table.com/docs/guides/column-filtering below:

Column Filtering Guide - Material React Table V3 Docs

Column Filtering Feature Guide

Filtering is one of the most powerful features of Material React Table and is enabled by default. There is a lot of flexibility and customization available here. Whether you want to customize the powerful client-side filtering already built in or implement your own server-side filtering, Material React Table has got you covered.

Relevant Table Options

#

Prop Name

Type

Default Value

More Info Links

1

Array<MRT_FilterOption | string> | null

MRT Column Filtering Docs  2 

boolean

false

MRT Column Filtering Docs 3

boolean

true

MRT Column Filtering Docs 4

boolean

true

TanStack Filters Docs 5

boolean

true

MRT Column Filtering Docs 6

boolean

true

TanStack Filters Docs 7

Record<string, FilterFn>

TanStack Table Filters Docs  8 

boolean

false

TanStack Filtering Docs 9

() => Map<any, number>

TanStack Table Filters Docs  10 

() => RowModel<TData>

TanStack Table Filters Docs  11 

() => Map<any, number>

TanStack Table Filters Docs  12 

() => RowModel<TData>

TanStack Table Filters Docs  13 

boolean

TanStack Table Filters Docs  14 

number

100

TanStack Table Filtering Docs 15

AutocompleteProps | ({ column, rangeFilterIndex, table }) => AutocompleteProps

Material UI Autocomplete Props  16 

CheckboxProps | ({ column, table}) => CheckboxProps

Material UI Checkbox Props  17 

DatePickerProps | ({ column, rangeFilterIndex, table }) => DatePickerProps

MUI X DatePicker Props  18 

DateTimePickerProps | ({ column, rangeFilterIndex, table }) => DateTimePickerProps

MUI X DateTimePicker Props  19 

SliderProps | ({ column, table}) => SliderProps

Material UI Slider Props  20 

TextFieldProps | ({ table, column, rangeFilterIndex}) => TextFieldProps

Material UI TextField Props  21 

TimePickerProps | ({ column, rangeFilterIndex, table }) => TimePickerProps

MUI X TimePicker Props  22 

OnChangeFn<{ [key: string]: MRT_FilterOption }>

  23 

OnChangeFn<ColumnFiltersState>

TanStack Table Filter Docs  24 

OnChangeFn<boolean>

  25 

({ column, internalFilterOptions, onSelectFilterMode, table }) => ReactNode[]

  Relevant Column Options

#

Column Option

Type

Default Value

More Info Links

1

Array<string>

  2 

boolean

MRT Column Filtering Docs  3 

boolean

MRT Column Filtering Docs  4 

boolean

MRT Column Filtering Docs  5 

({ column, header, table }) => ReactNode

MRT Column Filtering Docs  6 

MRT_FilterFn

'fuzzy'

7

Array<string | { label: string; value: string }>

  8 

'text' | 'select' | 'multi-select' | 'range' | 'range-slider' | 'checkbox' | 'autocomplete' | 'date' | 'date-range' | 'datetime' | 'datetime-range' | 'time' | 'time-range'

'text'

9

AutocompleteProps | ({ column, rangeFilterIndex, table }) => AutocompleteProps

MUI X DatePicker Props  10 

CheckboxProps | ({ column, table }) => CheckboxProps

Material UI Checkbox Props  11 

DatePickerProps | ({ column, rangeFilterIndex, table }) => DatePickerProps

MUI X DatePicker Props  12 

DateTimePickerProps | ({ column, rangeFilterIndex, table }) => DateTimePickerProps

MUI X DateTimePicker Props  13 

SliderProps | ({ column, table}) => SliderProps

Material UI Slider Props  14 

TextFieldProps | ({ column, rangeFilterIndex, table }) => TextFieldProps

Material UI TextField Props  15 

TimePickerProps | ({ column, rangeFilterIndex, table }) => TimePickerProps

MUI X TimePicker Props  16 

  Relevant State Options

#

State Option

Type

Default Value

More Info Links

1

{ [key: string]: MRT_FilterFn }

  2 

Array<{id: string, value: unknown}>

{}

TanStack Table Filters Docs 3

boolean

false

Disable Filtering Features

Various subsets of filtering features can be disabled. If you want to disable filtering completely, you can set the enableColumnFilters table option to false to remove all filters from each column. Alternatively, enableColumnFilter can be set to false for individual columns.

enableFilters can be set to false to disable both column filters and the global search filter.

Filter Variants

Material React Table has several built-in filter variants for advanced filtering. These can be specified on a per-column basis using the filterVariant option. The following variants are available:

'autocomplete', 'date', and 'date-range', variants are new in v2.0.0

datetime, datetime-range, time, and time-range variants are new in v2.4.0

Status

Filter by Status

Name

Salary

$30,000.00$200,000.00

Age

City

Filter by City

State

Filter by State

Hire Date

Arrival Time

Departure Time

Active Tanner Linsley $100,000.00 42 San Francisco California 2/23/2016 2/23/2016 6:25:43 PM 5:19:58 PM Active Kevin Vandy $80,000.00 51 Richmond Virginia 2/23/2019 2/23/2019 6:21:43 PM 8:53:12 PM Inactive John Doe $120,000.00 27 Riverside South Carolina 2/23/2014 2/23/2014 6:25:43 PM 12:07:56 PM Active Jane Doe $150,000.00 32 San Francisco California 2/25/2015 2/25/2015 6:25:43 PM 9:01:34 PM Inactive John Smith $75,000.00 42 Los Angeles California 6/11/2023 6/11/2023 6:25:43 PM 9:17:49 PM Active Jane Smith $56,000.00 51 Blacksburg Virginia 2/23/2019 2/23/2019 6:21:43 PM 6:12:46 AM Inactive Samuel Jackson $90,000.00 27 New York New York 2/23/2010 2/23/2010 6:25:43 PM 3:40:41 AM

1import { useMemo } from 'react';

2import {

3 MaterialReactTable,

4 useMaterialReactTable,

5 type MRT_ColumnDef,

6} from 'material-react-table';

7import { citiesList, data, type Person, usStateList } from './makeData';

8

9const Example = () => {

10 const columns = useMemo<MRT_ColumnDef<Person>[]>(

11 () => [

12 {

13 header: 'Status',

14 accessorFn: (originalRow) => (originalRow.isActive ? 'true' : 'false'),

15 id: 'isActive',

16 filterVariant: 'checkbox',

17 Cell: ({ cell }) =>

18 cell.getValue() === 'true' ? 'Active' : 'Inactive',

19 size: 170,

20 },

21 {

22 accessorKey: 'name',

23 header: 'Name',

24 filterVariant: 'text',

25 size: 200,

26 },

27 {

28 accessorKey: 'salary',

29 header: 'Salary',

30 Cell: ({ cell }) =>

31 cell.getValue<number>().toLocaleString('en-US', {

32 style: 'currency',

33 currency: 'USD',

34 }),

35 filterVariant: 'range-slider',

36 filterFn: 'betweenInclusive',

37 muiFilterSliderProps: {

38 marks: true,

39 max: 200_000,

40 min: 30_000,

41 step: 10_000,

42 valueLabelFormat: (value) =>

43 value.toLocaleString('en-US', {

44 style: 'currency',

45 currency: 'USD',

46 }),

47 },

48 },

49 {

50 accessorKey: 'age',

51 header: 'Age',

52 filterVariant: 'range',

53 filterFn: 'between',

54 size: 80,

55 },

56 {

57 accessorKey: 'city',

58 header: 'City',

59 filterVariant: 'select',

60 filterSelectOptions: citiesList,

61 },

62 {

63 accessorKey: 'state',

64 header: 'State',

65 filterVariant: 'multi-select',

66 filterSelectOptions: usStateList,

67 },

68 {

69 accessorFn: (originalRow) => new Date(originalRow.hireDate),

70 id: 'hireDate',

71 header: 'Hire Date',

72 filterVariant: 'date-range',

73 Cell: ({ cell }) => cell.getValue<Date>().toLocaleDateString(),

74 },

75 {

76 accessorFn: (originalRow) => new Date(originalRow.arrivalTime),

77 id: 'arrivalTime',

78 header: 'Arrival Time',

79 filterVariant: 'datetime-range',

80 Cell: ({ cell }) =>

81 `${cell.getValue<Date>().toLocaleDateString()} ${cell

82 .getValue<Date>()

83 .toLocaleTimeString()}`,

84 },

85 {

86 accessorFn: (originalRow) => new Date(originalRow.departureTime),

87 id: 'departureTime',

88 header: 'Departure Time',

89 filterVariant: 'time-range',

90 Cell: ({ cell }) => cell.getValue<Date>().toLocaleTimeString(),

91 },

92 ],

93 [],

94 );

95

96 const table = useMaterialReactTable({

97 columns,

98 data,

99 initialState: { showColumnFilters: true },

100 });

101

102 return <MaterialReactTable table={table} />;

103};

104

105

106import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';

107import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';

108

109const ExampleWithLocalizationProvider = () => (

110

111 <LocalizationProvider dateAdapter={AdapterDayjs}>

112 <Example />

113 </LocalizationProvider>

114);

115

116export default ExampleWithLocalizationProvider;

117

Faceted Values for Filter Variants

Faceted values are a list of unique values for a column that gets generated under the hood from table data when the enableFacetedValues table option is set to true. These values can be used to populate the select dropdowns for the 'select' and 'multi-select' filter variants, or the min and max values for the 'range-slider' variant. This means that you no longer need to manually specify the filterSelectOptions table option for these variants manually, especially if you are using client-side filtering.

Name

Salary

$56,000.00$150,000.00

City

Filter by City

State

Filter by State

Tanner Linsley $100,000.00 San Francisco California Kevin Vandy $80,000.00 Richmond Virginia John Doe $120,000.00 Riverside South Carolina Jane Doe $150,000.00 San Francisco California John Smith $75,000.00 Los Angeles California Jane Smith $56,000.00 Blacksburg Virginia Samuel Jackson $90,000.00 New York New York

1import { useMemo } from 'react';

2import {

3 MaterialReactTable,

4 useMaterialReactTable,

5 type MRT_ColumnDef,

6} from 'material-react-table';

7import { data, type Person } from './makeData';

8

9const Example = () => {

10 const columns = useMemo<MRT_ColumnDef<Person>[]>(

11 () => [

12 {

13 accessorKey: 'name',

14 header: 'Name',

15 filterVariant: 'autocomplete',

16 size: 100,

17 },

18 {

19 accessorKey: 'salary',

20 header: 'Salary',

21 Cell: ({ cell }) =>

22 cell.getValue<number>().toLocaleString('en-US', {

23 style: 'currency',

24 currency: 'USD',

25 }),

26 filterVariant: 'range-slider',

27 filterFn: 'betweenInclusive',

28 muiFilterSliderProps: {

29

30 marks: true,

31 step: 5_000,

32 valueLabelFormat: (value) =>

33 value.toLocaleString('en-US', {

34 style: 'currency',

35 currency: 'USD',

36 }),

37 },

38 },

39 {

40 accessorKey: 'city',

41 header: 'City',

42 filterVariant: 'select',

43

44 },

45 {

46 accessorKey: 'state',

47 header: 'State',

48 filterVariant: 'multi-select',

49

50 },

51 ],

52 [],

53 );

54

55 const table = useMaterialReactTable({

56 columns,

57 data,

58 enableFacetedValues: true,

59 initialState: { showColumnFilters: true },

60 });

61

62 return <MaterialReactTable table={table} />;

63};

64

65export default Example;

66

Custom Faceted Values

If you are using server-side pagination and filtering, you can still customize the faceted values output with the getFacetedUniqueValues and getFacetedMinMaxValues props.

const table = useMaterialReactTable({

columns,

data,

enableFacetedValues: true,

getFacetedMinMaxValues: (table) => {

return [minValue, maxValue];

},

getFacetedUniqueValues: (table) => {

const uniqueValueMap = new Map<string, number>();

return uniqueValueMap;

},

})

Column Filter Display Modes

By default, column filters inputs show below the column header. You can switch to a more "excel-like" UI by setting the columnFilterDisplayMode table option to 'popover'. This will show a filter icon in the column header that can be clicked to open a popover with the filter input.

const table = useMaterialReactTable({

columns,

data,

columnFilterDisplayMode: 'popover',

});

Alternatively, if you want to render your own column filter UI in a separate sidebar, but still want to use the built-in filtering functionality, you can set the columnFilterDisplayMode table option to 'custom'.

const table = useMaterialReactTable({

columns,

data,

columnFilterDisplayMode: 'custom',

});

ID

First Name

Last Name

Gender

Age

1 Hugh Mungus Male 42 2 Leroy Jenkins Male 51 3 Candice Nutella Female 27 4 Micah Johnson Other 32

1import { useMemo } from 'react';

2import {

3 MaterialReactTable,

4 useMaterialReactTable,

5 type MRT_ColumnDef,

6} from 'material-react-table';

7import { data, type Person } from './makeData';

8

9const Example = () => {

10 const columns = useMemo<MRT_ColumnDef<Person>[]>(

11 () => [

12 {

13 accessorKey: 'id',

14 header: 'ID',

15 },

16 {

17 accessorKey: 'firstName',

18 header: 'First Name',

19 },

20 {

21 accessorKey: 'lastName',

22 header: 'Last Name',

23 },

24 {

25 accessorKey: 'gender',

26 header: 'Gender',

27 filterFn: 'equals',

28 filterSelectOptions: ['Male', 'Female', 'Other'],

29 filterVariant: 'select',

30 },

31 {

32 accessorKey: 'age',

33 header: 'Age',

34 filterVariant: 'range',

35 },

36 ],

37 [],

38 );

39

40 const table = useMaterialReactTable({

41 columns,

42 data,

43 columnFilterDisplayMode: 'popover',

44 });

45

46 return <MaterialReactTable table={table} />;

47};

48

49export default Example;

50

Custom Filter Functions

You can specify either a pre-built filterFn that comes with Material React Table or pass in your own custom filter functions.

Custom Filter Functions Per Column

By default, Material React Table uses a fuzzy filtering algorithm based on the popular match-sorter library from Kent C. Dodds. However, Material React Table also comes with numerous other filter functions that you can specify per column in the filterFn column options.

Pre-built MRT Filter Functions

Pre-built filter functions from Material React Table include between, betweenInclusive, contains, empty, endsWith, equals, fuzzy, greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo, notEmpty, notEquals, and startsWith. View these algorithms here

Pre-built TanStack Table Filter Functions

Pre-built filter functions from TanStack Table include includesString, includesStringSensitive, equalsString, equalsStringSensitive, arrIncludes, arrIncludesAll, arrIncludesSome, weakEquals, and inNumberRange. View more information about these algorithms in the TanStack Table Filter docs.

You can specify either a pre-built filter function, from Material React Table or TanStack Table, or you can even specify your own custom filter function in the filterFn column option.

const columns = [

{

accessorKey: 'firstName',

header: 'First Name',

filterFn: 'startsWith',

},

{

accessorKey: 'middleName',

header: 'Middle Name',

filterFn: 'includesStringSensitive',

},

{

accessorKey: 'lastName',

header: 'Last Name',

filterFn: (row, id, filterValue) =>

row.getValue(id).startsWith(filterValue),

},

];

If you provide a custom filter function, it must have the following signature:

(row: Row<TData>, id: string, filterValue: string | number) => boolean;

This function will be used to filter 1 row at a time and should return a boolean indicating whether or not that row passes the filter.

Add Custom Filter Functions

You can add custom filter functions to the filterFns table option. These will be available to all columns to use. The filterFn table option on a column will override any filter function with the same name in the filterFns table option.

const columns = [

{

accessorKey: 'name',

header: 'Name',

filterFn: 'customFilterFn',

},

];

const table = useMaterialReactTable({

columns,

data,

filterFns: {

customFilterFn: (row, id, filterValue) => {

return row.customField === value;

},

},

});

Filter Modes Enable Column Filter Modes (Filter Switching)

If you want to let the user switch between multiple different filter modes from a drop-down menu on the Filter Textfield, you can enable that with the enableColumnFilterModes table option or column option. This will enable the filter icon in the filter text field to open a drop-down menu with the available filter modes when clicked.

const table = useMaterialReactTable({

columns,

data,

enableColumnFilterModes: true,

});

Customize Filter Modes

You can narrow down the available filter mode options by setting the columnFilterModeOptions table option or a column specific columnFilterModeOptions option.

const columns = [

{

accessorKey: 'firstName',

header: 'First Name',

columnFilterModeOptions: ['fuzzy', 'contains', 'startsWith'],

},

{

accessorKey: 'age',

header: 'Age',

columnFilterModeOptions: ['between', 'lessThan', 'greaterThan'],

},

];

You can also render custom menu items in the filter mode drop-down menu by setting the renderColumnFilterModeMenuItems table option or column option. This option is a function that takes in the column and returns an array of MenuItem components. This is useful if you want to add custom filter modes that are not included in Material React Table, or if you just want to render the menu in your own custom way

const columns = [

{

accessorKey: 'firstName',

header: 'First Name',

renderColumnFilterModeMenuItems: ({ column, onSelectFilterMode }) => [

<MenuItem

key="startsWith"

onClick={() => onSelectFilterMode('startsWith')}

>

Start With

</MenuItem>,

<MenuItem

key="endsWith"

onClick={() => onSelectFilterMode('yourCustomFilterFn')}

>

Your Custom Filter Fn

</MenuItem>,

],

},

];

const table = useMaterialReactTable({

columns,

data,

enableColumnFilterModes: true,

});

return <MaterialReactTable table={table} />;

ID

First Name

Filter Mode: Fuzzy

Middle Name

Last Name

Filter Mode: Fuzzy

Age

Filter Mode: Between

1 Hugh Jay Mungus 42 2 Leroy Leroy Jenkins 51 3 Candice Denise Nutella 27 4 Micah Henry Johnson 32

1import { useMemo } from 'react';

2import {

3 MaterialReactTable,

4 useMaterialReactTable,

5 type MRT_ColumnDef,

6} from 'material-react-table';

7import { MenuItem } from '@mui/material';

8import { data, type Person } from './makeData';

9

10const Example = () => {

11 const columns = useMemo<MRT_ColumnDef<Person>[]>(

12 () => [

13 {

14 accessorKey: 'id',

15 enableColumnFilterModes: false,

16 filterFn: 'equals',

17 header: 'ID',

18 },

19 {

20 accessorKey: 'firstName',

21 header: 'First Name',

22 },

23 {

24 accessorKey: 'middleName',

25 enableColumnFilterModes: false,

26 filterFn: 'startsWith',

27 header: 'Middle Name',

28 },

29 {

30 accessorKey: 'lastName',

31 header: 'Last Name',

32

33 renderColumnFilterModeMenuItems: ({ onSelectFilterMode }) => [

34 <MenuItem key="0" onClick={() => onSelectFilterMode('contains')}>

35 <div>Contains</div>

36 </MenuItem>,

37 <MenuItem

38 key="1"

39 onClick={() => onSelectFilterMode('customFilterFn')}

40 >

41 <div>Custom Filter Fn</div>

42 </MenuItem>,

43 ],

44 },

45 {

46 accessorKey: 'age',

47 columnFilterModeOptions: ['between', 'greaterThan', 'lessThan'],

48 filterFn: 'between',

49 header: 'Age',

50 },

51 ],

52 [],

53 );

54

55 const table = useMaterialReactTable({

56 columns,

57 data,

58 enableColumnFilterModes: true,

59 initialState: { showColumnFilters: true },

60 filterFns: {

61 customFilterFn: (row, id, filterValue) => {

62 return row.getValue(id) === filterValue;

63 },

64 },

65 localization: {

66 filterCustomFilterFn: 'Custom Filter Fn',

67 } as any,

68 });

69

70 return <MaterialReactTable table={table} />;

71};

72

73export default Example;

74

Expanded Leaf Row Filtering Options

If you are using the filtering features along-side either the grouping or expanding features, then there are a few behaviors and customizations you should be aware of.

Check out the Expanded Leaf Row Filtering Behavior docs to learn more about the filterFromLeafRows and maxLeafRowFilterDepth props.

Manual Server-Side Column Filtering

A very common use case when you have a lot of data is to filter the data on the server, instead of client-side. In this case, you will want to set the manualFiltering table option to true and manage the columnFilters state yourself like so (can work in conjunction with manual global filtering).

const [columnFilters, setColumnFilters] = useState([]);

const [data, setData] = useState([]);

useEffect(() => {

const fetchData = async () => {

const filteredData = await fetch();

setData([...filteredData]);

};

}, [columnFilters]);

const table = useMaterialReactTable({

columns,

data,

manualFiltering: true,

onColumnFiltersChange: setColumnFilters,

state: { columnFilters },

});

return <MaterialReactTable table={table} />;

Specifying manualFiltering turns off all client-side filtering and assumes that the data you pass to <MaterialReactTable /> is already filtered.

See either the React Query or useEffect fetching examples to see fully server-side filtering, pagination, and sorting in action.

Customize Material UI Filter components

You can customize the Material UI filter components by setting the muiFilterTextFieldProps table option or column option.

You can also turn a filter textfield into a select dropdown by setting the filterSelectOptions table option or column option.

ID

First Name

Last Name

Gender

Filter by Gender

Age

1 Hugh Mungus Male 42 2 Leroy Jenkins Male 51 3 Candice Nutella Female 27 4 Micah Johnson Other 32

1import { useMemo } from 'react';

2import {

3 MaterialReactTable,

4 useMaterialReactTable,

5 type MRT_ColumnDef,

6} from 'material-react-table';

7

8export type Person = {

9 id: number;

10 firstName: string;

11 lastName: string;

12 gender: string;

13 age: number;

14};

15

16const Example = () => {

17 const columns = useMemo<MRT_ColumnDef<Person>[]>(

18 () => [

19 {

20 accessorKey: 'id',

21 header: 'ID',

22 muiFilterTextFieldProps: { placeholder: 'ID' },

23 },

24 {

25 accessorKey: 'firstName',

26 header: 'First Name',

27 },

28 {

29 accessorKey: 'lastName',

30 header: 'Last Name',

31 },

32 {

33 accessorKey: 'gender',

34 header: 'Gender',

35 filterFn: 'equals',

36 filterSelectOptions: [

37 { label: 'Male', value: 'Male' },

38 { label: 'Female', value: 'Female' },

39 { label: 'Other', value: 'Other' },

40 ],

41 filterVariant: 'select',

42 },

43 {

44 accessorKey: 'age',

45 header: 'Age',

46 filterVariant: 'range',

47 },

48 ],

49 [],

50 );

51

52 const data = useMemo<Person[]>(

53

54 () => [

55 {

56 id: 1,

57 firstName: 'Hugh',

58 lastName: 'Mungus',

59 gender: 'Male',

60 age: 42,

61 },

62 {

63 id: 2,

64 firstName: 'Leroy',

65 lastName: 'Jenkins',

66 gender: 'Male',

67 age: 51,

68 },

69 {

70 id: 3,

71 firstName: 'Candice',

72 lastName: 'Nutella',

73 gender: 'Female',

74 age: 27,

75 },

76 {

77 id: 4,

78 firstName: 'Micah',

79 lastName: 'Johnson',

80 gender: 'Other',

81 age: 32,

82 },

83 ],

84 [],

85

86 );

87

88 const table = useMaterialReactTable({

89 columns,

90 data,

91 initialState: { showColumnFilters: true },

92 muiFilterTextFieldProps: {

93 sx: { m: '0.5rem 0', width: '100%' },

94 variant: 'outlined',

95 },

96 });

97

98 return <MaterialReactTable table={table} />;

99};

100

101export default Example;

102

Custom Filter Components

If you need custom filter components that are much more complex than text-boxes and dropdowns, you can create and pass in your own filter components using the Filter column option.

Filter Match Highlighting

Filter Match Highlighting is a new featured enabled by default that will highlight text in the table body cells that matches the current filter query with a shade of the theme.palette.warning.main color.

Filter Match Highlighting will only work on columns with the default text filter variant. Also, if you are using a custom Cell render override for a column, you will need to use the renderedCellValue table option instead of cell.getValue() in order to preserve the filter match highlighting.

const columns = [

{

accessorKey: 'name',

header: 'Name',

Cell: ({ renderedCellValue }) => <span>{renderedCellValue}</span>,

},

];

Disable Filter Match Highlighting

This feature can be disabled by setting the enableFilterMatchHighlighting table option to false.

const table = useMaterialReactTable({

columns,

data,

enableFilterMatchHighlighting: false,

});

View Extra Storybook Examples


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4